Подскажите пожалуйста - как работает GuiDispatcher.AddPeriodicalAction? Судя из названия метода - действие вызывается периодически - но с какой частотой. Пример использования встречается в SampleGui, где с помощью этого метода обновляется информация в открытых стаканах. Логика там, как я понимаю, следующая - ведется два синхронизированных словаря ключ-значение: один - инструмент/окно стакана, другой - рыночный стакан/окно стакана.
private readonly SynchronizedDictionary<Security, QuotesWindow> _quotesWindows = new SynchronizedDictionary<Security, QuotesWindow>();
private readonly SynchronizedDictionary<MarketDepth, QuotesWindow> _changedDepths = new SynchronizedDictionary<MarketDepth, QuotesWindow>();
Далее происходит подписка на обновление стаканов trader.MarketDepthsChanged += TraderOnMarketDepthsChanged, и вот совсем мне непонятно, что делается в TraderOnMarketDepthsChanged:
private void TraderOnMarketDepthsChanged(IEnumerable<MarketDepth> depths)
{
foreach (var depth in depths)
{
var wnd = _quotesWindows.TryGetValue(depth.Security);
if (wnd != null)
_changedDepths[depth] = wnd;
}
}
Что тут происходит, как я понимаю: рассматриваем каждый обновившийся стакан и ищем соответствующее ему окно стакана в _quotesWindows: var wnd = _quotesWindows.TryGetValue(depth.Security);
Далее что происходит в этой строчке: _changedDepths[depth] = wnd; ? Откуда мы знаем, что в словаре _changedDepths есть элемент с ключом depth? И зачем на каждом обновлении стакана depth мы переприсваиваем значение wnd в словаре? Ну и самый главные вопрос - как потом в wnd появляются новые котировки с обновленного depth? Как работает .AddPeriodicalAction?
Просто я думал логика должна была быть примерно такая - достаточно держать лишь один словарь - _quotesWindows и при получении обновленного MarketDepth - найти соответствующий ему элемент в _quotesWindows и обновить _quotesWindows.Value. Разве не так?
Я еще только начинаю разбираться в программировании такого уровня, так что сильно не бейте и спасибо за помощь.
Kommentare (7)
Anmelden oder Konto erstellen, Melden Sie sich an oder registrieren Sie sich, um einen Kommentar zu hinterlassen
Или другими словами можно было бы исключить
т.к. между экземпляром инструмента (Security) и экземпляром стакана (MarketDepth) существует однозначная связь, а security - экземпляр Security определяется, как из экземпляра стакана depth (MarketDepth), так и экз-ра котировок стакана, привязанного к окну QuotesWindow (ObservableCollection<Quote>)
Но, в наст. реализации, _quotesWindows - это экземпляр окна котировок, содержащее коллекцию котировок, не содержащие внутри себя идентификацию инструмента (стакана) или стакана (инструмента) этих котировок:
Зато для этого есть словари, из которых по экземпляру инструментов (Security) или стаканов (MarketDepth) можно извлечь экземпляр коллекции котировок - QuotesWindow, т.е. ObservableCollection<Quote>
Насколько я понимаю, есть другие необходимости
В общем, неочевидно, что нужны твкие усложнения, при том, что теряется гибкость и структурность + см. следующее соображение
private void TraderOnMarketDepthsChanged(IEnumerable<MarketDepth> depths) { foreach (var depth in depths) { var wnd = _quotesWindows.TryGetValue(depth.Security);
}
Вот тут тоже спорно и непонятно, ведь именно в TraderOnMarketDepthsChanged никакого обновления ни одной котировки не происходит - тут то и беда. Оно происходит только в диспатчере этом. И вот такая запутанность непонятна. В TraderOnMarketDepthsChanged только копирование по ссылке значений происходит (опять же непонятно зачем). Короче совсем каша какая-то.
Огромное спасибо за такой развернутый ответ. Все практически встало на свои места. Остался один вопрос по теме - как все таки работает "синхронизация" мд этими двумя словарями? Вот мы их проинициализировали - два словаря с одинаковыми значениями, но разными ключами. Неужели этого достаточно для того, чтобы если в одном словаре появился новый элемент, то он появился и в другом? Я честно гуглил,но так и не понял как работает этот класс.
И есть еще один вопрос, который связан с моими непониманием некоторых особенностей языка. Помогите пожалуйста также наглядно разобраться с объектом класса GuiDispatcher : _dispatcher. Вот в том же примере в том же классе SecuritiesWindow встречается такой код:
Как я понимаю, что тут происходит: AddPeriodicalAction, как следует из названия, вызывает с какой-то (с какой???) периодичностью нижеидущее действие, которое, в свою очередь, заполняет QuotesWindow из MarketDepth. Как же все таки истинно работает этот диспатчер - в чем его обязанность, удобство перед таймером или вообще необходимость?
Ведь теперь получается совершенно запутанная последовательность действия, как я понимаю. Вот у нас есть два словаря, пока что пустых. Пользователь кликает по кнопке создать стакан и в словарь _quotesWindows добавляется элемент А = (Security, QuotesWindow). По идее, следуя из того, что словари синхронизированы (хотя я до сих пор не понимаю, как это осуществляется, где и кем) в словаре _changedDepths появляется элемент В = (MarketDepth, QuotesWindow). Причем А и В имеют одно и тоже значение,а ключи разные, хотя и соответствуют одному и тому же инструменту. Далее в TraderOnMarketDepthsChanged по каждому обновленному MarketDepth делается что-то невероятное: ищется соответствующий ему элемент в _quotesWindows и соответствующий ему элемент в _changedDepths, после этого QuotesWindow из первого присваивается второму. Зачем?!Вот этот момент мне не понятен. Далее, как раз с помощью диспатчера (что мне тоже непонятно, но выше я уже это спросил) в _changedDepths во всех элементах берутся котировки из ключа и пихаются в значение. Таким образом мы наконец-то получаем обновленный QuotesWindow (то есть в стакане нашем, наконец-то появляются обновленные котировки). Но это же адово сложный процесс.
Ведь можно, как вы сказали выше, вести только один словарь _changedDepths, и в событии TraderOnMarketDepthsChanged делать то, что делается в _dispatcher.AddPeriodicalAction и результат по идее дб тот же. Или нет? Спасибо заранее за пояснения. А то оч уж сложная механика, для вроде кажущихся несложный действий.
Открываем, смотрим:
Переходим по StartTimer:
Видим создание объекта типа DispatcherTimer. Полное имя - System.Windows.Threading.DispatcherTimer, что это за класс можно почитать на MSDN. Дальше интересна строчка:
Точнее this.Interval.Ticks. Переходим по Interval и видим следующее:
И последний переход по _interval, в то место где данное поле инициализируется:
В итоге по умолчания AddPeriodicalAction работает с периодичностью = TimeSpan.FromMilliseconds(100.0).Ticks / 10L.
Хм, спасибо снова за такие пояснения. Не все понятно в середине, но важен итог - получается AddPeriodicalAction вызывается каждые 10мс? Тогда остается открытой эта часть моего вопроса:
" Ведь теперь получается совершенно запутанная последовательность действия, как я понимаю. Вот у нас есть два словаря, пока что пустых. Пользователь кликает по кнопке создать стакан и в словарь _quotesWindows добавляется элемент А = (Security, QuotesWindow). По идее, следуя из того, что словари синхронизированы (хотя я до сих пор не понимаю, как это осуществляется, где и кем) в словаре _changedDepths появляется элемент В = (MarketDepth, QuotesWindow). Причем А и В имеют одно и тоже значение,а ключи разные, хотя и соответствуют одному и тому же инструменту. Далее в TraderOnMarketDepthsChanged по каждому обновленному MarketDepth делается что-то невероятное: ищется соответствующий ему элемент в _quotesWindows и соответствующий ему элемент в _changedDepths, после этого QuotesWindow из первого присваивается второму. Зачем?!Вот этот момент мне не понятен. Далее, как раз с помощью диспатчера (что мне тоже непонятно, но выше я уже это спросил) в _changedDepths во всех элементах берутся котировки из ключа и пихаются в значение. Таким образом мы наконец-то получаем обновленный QuotesWindow (то есть в стакане нашем, наконец-то появляются обновленные котировки). Но это же адово сложный процесс.
Ведь можно, как вы сказали выше, вести только один словарь _changedDepths, и в событии TraderOnMarketDepthsChanged делать то, что делается в _dispatcher.AddPeriodicalAction и результат по идее дб тот же. Или нет? Спасибо заранее за пояснения. А то оч уж сложная механика, для вроде кажущихся несложный действий. "
И к тому же добавляется еще один - а не накладно каждые 10мс вызывать обновление всего списка котировок, вместо того, чтобы обновлять его по событию?
Ну, дак в соответствии с Вами же процитированным кодом:
Понятно, то есть одним словом в примере немного мудрено реализован механизм?