Нужно доделать потоки с заявками, сделками (собственными и тиковыми). Сейчас через потоки заполняются только инструменты, портфели, стаканы и позиции.
PlazaStreamManager сейчас создает отдельные потоки для каждного стрима. Расточительно по ресурсам. Лучшем переделать на ThreadPool. И да, кто может мне объяснить в чем смысл всех этих ProcessMessage?
Логику PlazaTableSerializer лучше перекинуть в PlazaSchemaParser. И да, можно ли построить логику PlazaSchemaParser на основе IniConfigParser?
Mikhail Sukhov:
PlazaStreamManager сейчас создает отдельные потоки для каждного стрима. Расточительно по ресурсам. Лучшем переделать на ThreadPool.
Займусь.
Mikhail Sukhov:
И да, кто может мне объяснить в чем смысл всех этих ProcessMessage?
Это такой протокол. См. стр. 7 P2ClientFate.doc:
5.2. Принципы работы с соединениями в API
Работа с соединениями производится по стандартному шаблону:
• Создание объекта IP2Connection.
• Вызов метода Connect — при его успешном завершении устанавливается локальное соединение с роутером.
• Запуск бесконечного цикла, в котором происходит вызов функции ProcessMessage для соединения.
Mikhail Sukhov:
Логику PlazaTableSerializer лучше перекинуть в PlazaSchemaParser.
PlazaSchemaParser не используется вообще. Я его оставил, потому что уже сделал и жалко было выкидывать готовый, хотя и сырой, парсер ini-файлов потоков репликации. Может быть оставим PlazaTableSerializer и выкинем PlazaSchemaParser?
Mikhail Sukhov:
И да, можно ли построить логику PlazaSchemaParser на основе IniConfigParser?
Наверное, да. Но можем усложнить жизнь. Синтаксис в ini-файлов потоков репликации немного отличается (чуть сложнее). Может быть оставим, как есть?
Mikhail Sukhov:
Кто что сделает?
Таким образом беру 2 и 3.
Mikhail Sukhov:
PlazaStreamManager сейчас создает отдельные потоки для каждного стрима. Расточительно по ресурсам. Лучшем переделать на ThreadPool.
Займусь.
aspirant:
Это такой протокол. См. стр. 7 P2ClientFate.doc:
Прочитал. Не понял насчет интенсивности вызова этого метода. Я могу какое-то сообщение пропустить, если не успею вызвать метод ProcessMessage? Или они где-то копяться? С чем тогда прикол этого метода? Почему нельзя просто подписаться на событие и получать данные через него?
Меня еще смутил параметр PollInterval, который передавался в ProcessMessage. Прочитал доку, оказалось что это не PollInterval, а PollTimeout. Стало понятнее. Я так понял, это то время, на которое будет заблокирован метод ProcessMessage, если не будет нового сообщения?
Видел интерфейс IP2MessageReceiver? Я вот думаю, а это случайно не альтернатива ProcessMessage, только без вечного цикла?
aspirant:
PlazaSchemaParser не используется вообще. Я его оставил, потому что уже сделал и жалко было выкидывать готовый, хотя и сырой, парсер ini-файлов потоков репликации. Может быть оставим PlazaTableSerializer и выкинем PlazaSchemaParser?
Как тебе будет виднее. Но R# говорит, что PlazaSchemaParser все же используется. И, судя по коду, PlazaTableSerializer пишет ini схемы, а PlazaSchemaParser читает. А нам вроде бы и то и другое нужно для работы.
aspirant:
Наверное, да. Но можем усложнить жизнь. Синтаксис в ini-файлов потоков репликации немного отличается (чуть сложнее). Может быть оставим, как есть?
Mikhail Sukhov:
Прочитал. Не понял насчет интенсивности вызова этого метода. Я могу какое-то сообщение пропустить, если не успею вызвать метод ProcessMessage? Или они где-то копяться? С чем тогда прикол этого метода? Почему нельзя просто подписаться на событие и получать данные через него?
Алгоритм подписки на потоки брал из примера плазовцев. Там этот метод вызывается в отдельном thread'е в непрерывном цикле. Во вторник попробую закомментить вызов этого метода и посмотреть, идут ли данные из потоков. Почему они так сделали, мне тоже непонятно.
Mikhail Sukhov:
Меня еще смутил параметр PollInterval, который передавался в ProcessMessage. Прочитал доку, оказалось что это не PollInterval, а PollTimeout.
PollInterval сейчас исправлю на PollTimeout. Я почему-то поменял название этого параметра🤨
Mikhail Sukhov:
Я так понял, это то время, на которое будет заблокирован метод ProcessMessage, если не будет нового сообщения?
Да, это так.
Mikhail Sukhov:
Видел интерфейс IP2MessageReceiver? Я вот думаю, а это случайно не альтернатива ProcessMessage, только без вечного цикла?
В доке как-то все размыто написано. У меня создалось впечатление, что этот интерфейс не относится к данным из потоков. Он нужен для отправки заявок и т.д., а я в это не влезал вообще.
aspirant:
PlazaSchemaParser не используется вообще. Я его оставил, потому что уже сделал и жалко было выкидывать готовый, хотя и сырой, парсер ini-файлов потоков репликации. Может быть оставим PlazaTableSerializer и выкинем PlazaSchemaParser?
Как тебе будет виднее. Но R# говорит, что PlazaSchemaParser все же используется. И, судя по коду, PlazaTableSerializer пишет ini схемы, а PlazaSchemaParser читает. А нам вроде бы и то и другое нужно для работы.
Да, забыл. PlazaSchemaParser используется для десериализации данных из ini-файлов. Но эта фича нам пока не нужна, поэтому предлагаю вместо вызовов PlazaSchemaParser пока выкидывать NotImplementedException()?
Mikhail Sukhov:
PlazaStreamManager сейчас создает отдельные потоки для каждного стрима. Расточительно по ресурсам. Лучшем переделать на ThreadPool.
Займусь.
Готово
Смотрел. Небольшой ликбез по работе пула потоков. В пул потоков мы помещаем небольшие действия, которых может быть очень много, но при этом отрабатывают они быстро. У тебя же помещается вечный цикл, что не является быстрой отработкой.
Идея работы пула в рамках PlazaStreamManager мне видется в заведении таймера (который Threading.Timer, потому что он основан на пуле потоков), в обработчике которого будут перебираться все соединения, и для них будет вызываться ProcessMessage. Тоесть, как только один "зависнет" в ожидании сообщения, таймер создаст еще один пуловый поток, который будет обрабатывать следующее свободное соединение (иначе все потоки будут ждать одно и то же соединение).
Mikhail Sukhov:
Смотрел. Небольшой ликбез по работе пула потоков. В пул потоков мы помещаем небольшие действия, которых может быть очень много, но при этом отрабатывают они быстро. У тебя же помещается вечный цикл, что не является быстрой отработкой.
Насчет Threadpool'а знаю. Именно из-за этого изначально создавал полноценные Thread'ы.
Mikhail Sukhov:
Идея работы пула в рамках PlazaStreamManager мне видется в заведении таймера (который Threading.Timer, потому что он основан на пуле потоков), в обработчике которого будут перебираться все соединения, и для них будет вызываться ProcessMessage. Тоесть, как только один "зависнет" в ожидании сообщения, таймер создаст еще один пуловый поток, который будет обрабатывать следующее свободное соединение (иначе все потоки будут ждать одно и то же соединение).
У меня здесь вот какое предложение. Сейчас мы для каждого стрима создаем отдельный Connection. А что если мы пойдем по более простому пути, как в примере у плазовцев: все стримы используют один Connection. В этом случае создается только один Thread, внутри которого в бесконечном цикле вызвается ProcessMessage. Если будут тормоза, тогда уже будем делать, как ты предлагаешь. Напиши, что думаешь.
aspirant:
У меня здесь вот какое предложение. Сейчас мы для каждого стрима создаем отдельный Connection. А что если мы пойдем по более простому пути, как в примере у плазовцев: все стримы используют один Connection. В этом случае создается только один Thread, внутри которого в бесконечном цикле вызвается ProcessMessage. Если будут тормоза, тогда уже будем делать, как ты предлагаешь. Напиши, что думаешь.
Исправил код. У тебя там хитрая логика с остановкой и перезапуском потока была, которая по сути не нужно вообще. Ну что это за робот, которому потоки не нужно?🙂 Поток пуская живет все время и закрывается при закрытие PlazaTrader. Меньше сложностей, меньша багов.
aspirant:
Да, забыл. PlazaSchemaParser используется для десериализации данных из ini-файлов. Но эта фича нам пока не нужна, поэтому предлагаю вместо вызовов PlazaSchemaParser пока выкидывать NotImplementedException()?
aspirant:
Да, забыл. PlazaSchemaParser используется для десериализации данных из ini-файлов. Но эта фича нам пока не нужна, поэтому предлагаю вместо вызовов PlazaSchemaParser пока выкидывать NotImplementedException()?
aspirant:
Да, забыл. PlazaSchemaParser используется для десериализации данных из ini-файлов. Но эта фича нам пока не нужна, поэтому предлагаю вместо вызовов PlazaSchemaParser пока выкидывать NotImplementedException()?
как же вы 4 месяца занимались Плазой и только теперь выясняете, что такое ProcessMessage?
судя по техническому форуму РТС, без ясного понимания, как это работает, легко получить тормозящий код.
проконсультируйтесь с Кукушкиным, который вроде хорошо разобрался. Или с ртс-овцами. Дока там ужасная.
Или я не понимаю схему работы сообщений от Плазы, или там обсуждается какая-то ерунда. Таймаут надо ставить по максимуму, так как он дает возможность не вызывать в холостую метод ProcessMessage. Ставить 1 милилсекунду нет никакого смысла, так как данные от Плазы накапливаются (это я так думаю), и все равно ничего не пропустится.
Mikhail Sukhov:
Или я не понимаю схему работы сообщений от Плазы, или там обсуждается какая-то ерунда. Таймаут надо ставить по максимуму, так как он дает возможность не вызывать в холостую метод ProcessMessage. Ставить 1 милилсекунду нет никакого смысла, так как данные от Плазы накапливаются (это я так думаю), и все равно ничего не пропустится.
Вот механизм работы:
Таймаут - это сколько висеть на сокете в ожидании пакета данных, если пакет уже есть, то метод вернется сразу как только обработаются все события получения данных.
Остальное, да, вода. Поток используется только под этот метод, поэтому ставить маленькие периоды смысла нет.
Mikhail Sukhov:
Или я не понимаю схему работы сообщений от Плазы, или там обсуждается какая-то ерунда. Таймаут надо ставить по максимуму, так как он дает возможность не вызывать в холостую метод ProcessMessage. Ставить 1 милилсекунду нет никакого смысла, так как данные от Плазы накапливаются (это я так думаю), и все равно ничего не пропустится.
Вот механизм работы:
Таймаут - это сколько висеть на сокете в ожидании пакета данных, если пакет уже есть, то метод вернется сразу как только обработаются все события получения данных.
Остальное, да, вода. Поток используется только под этот метод, поэтому ставить маленькие периоды смысла нет.
Вот и возник вопрос. Есть сообщения копяться от Плазы, зачем тогда вообще вызывать ProcessMessage? Почему не сделали просто вызов события?
Mikhail Sukhov:
Вот и возник вопрос. Есть сообщения копяться от Плазы, зачем тогда вообще вызывать ProcessMessage? Почему не сделали просто вызов события?
Не знаю, но без вызова точно не работает. Только что еще раз проверил.
Mikhail Sukhov:
Вот и возник вопрос. Есть сообщения копяться от Плазы, зачем тогда вообще вызывать ProcessMessage? Почему не сделали просто вызов события?
Не знаю, но без вызова точно не работает. Только что еще раз проверил.
=) Я верю что не работает. С первого раза поверил. Но думаю тут не спроста. Или косяк в архитектуре Плазы (не удивлюсь) или мы что-то упустили.
Mikhail Sukhov:
=) Я верю что не работает. С первого раза поверил.
Это я сам себя проверял. Порой кажется, что все сделал правильно, а упустишь какую-то мелочь и приходится есть свой галстук. Образно, конечно🙂
Mikhail Sukhov:
Но думаю тут не спроста. Или косяк в архитектуре Плазы (не удивлюсь) или мы что-то упустили.
Мне все-таки кажется, что первое. Повторюсь: алгоритм взят из их примера BaselessClient.
ProcessMessage это прокачка очереди сообщений на сокете "вручную". Почему сделано так, а не иначе хз. Для совместимости чего-то с чем-то. Без понимания всех нюансов (а их там много) может быть плохо, потому что внутри есть критические секции, при работе с одним объектом из разных тредов может происходить маршаллинг. Общее правило кажется(!) один поток - один объект коннекшн.
Bell:
ProcessMessage это прокачка очереди сообщений на сокете "вручную". Почему сделано так, а не иначе хз. Для совместимости чего-то с чем-то. Без понимания всех нюансов (а их там много) может быть плохо, потому что внутри есть критические секции, при работе с одним объектом из разных тредов может происходить маршаллинг. Общее правило кажется(!) один поток - один объект коннекшн.
Это как бы правило МТА. Только все равно не понятно насчет ProcessMessage.
Mikhail Sukhov:
Только все равно не понятно насчет ProcessMessage.
Почему так сделано? Это надо спрашивать у разработчиков. Они это где-то объясняли, но я не понял. У меня на Плазу вообще идиосинкразия. Вот всё надеялся, что вы сделаете нормально...
Mikhail Sukhov:
Только все равно не понятно насчет ProcessMessage.
Почему так сделано? Это надо спрашивать у разработчиков. Они это где-то объясняли, но я не понял. У меня на Плазу вообще идиосинкразия. Вот всё надеялся, что вы сделаете нормально...
Mikhail Sukhov:
Почему в прошедшем времени?🙂
ок, буду ждать 🙂
но еще раз посоветую проконсультироваться по разным таким нюансам с теми, кто разобрался. Вот Кукушкин на техфоруме РТС очень доброжелательный чел.
Mikhail Sukhov:
Почему в прошедшем времени?🙂
ок, буду ждать 🙂
но еще раз посоветую проконсультироваться по разным таким нюансам с теми, кто разобрался. Вот Кукушкин на техфоруме РТС очень доброжелательный чел.
Хорошо, перед сертификацией PlazaTrader обязательно пройдем сертификацию Кукушкина.🙂
Mikhail Sukhov:
Там код получился один в один для фьючей и опцов. Может имеет смысл вынести в общий метод, как я с инструментами сделал? Или как со стаканами.
Сделал + залил заявки. В заявках по многим свойствам вопросы. Посмотришь исходник? Может быть нужно мапить из еще одной таблицы (OrdersLogFutureStream / OrdersLogOptionStream)🤨 Но это уже завтра. Elvis has left the building...
Mikhail Sukhov:
Там код получился один в один для фьючей и опцов. Может имеет смысл вынести в общий метод, как я с инструментами сделал? Или как со стаканами.
Сделал + залил заявки. В заявках по многим свойствам вопросы. Посмотришь исходник? Может быть нужно мапить из еще одной таблицы (OrdersLogFutureStream / OrdersLogOptionStream)🤨 Но это уже завтра. Elvis has left the building...
Удалил это, так как это неправильно.
static PlazaColumnRegistry()
{
// Без этого конструктора клиенту нельзя добавить колонки.
}
Статический конструктор есть всегда. Он или нами явно определяется, или его компилятор "дописывает".
Посмотрел и поправил код. Но у меня почему то заявки не идут с Плазы. Выставил по рынку - ни одного уведомления. Перезапустил прогу, опять ничего по заявкам.
static PlazaColumnRegistry()
{
// Без этого конструктора клиенту нельзя добавить колонки.
}
>
> Статический конструктор есть всегда. Он или нами явно определяется, или его компилятор "дописывает".
Добавь у себя в Connect_Click GUI клиента сразу после инициализации Trader вот этот кусок кода:
И запусти GUI клиент. У меня при попытке подключения срабатывает ArgumentNullException. С явным статическим конструктором PlazaColumnRegistry() исключения нет. Меняется порядок инициализации статических классов? Шаманство🤨 Вчера уже не успевал влезть в суть.
> **[Mikhail Sukhov](@message(8071)):**
> Но у меня почему то заявки не идут с Плазы. Выставил по рынку - ни одного уведомления. Перезапустил прогу, опять ничего по заявкам.
Нужно копать. А как выставить заявку в GUI-примере?
> И запусти GUI клиент. У меня при попытке подключения срабатывает ArgumentNullException. С явным статическим конструктором PlazaColumnRegistry() исключения нет. Меняется порядок инициализации статических классов? Шаманство🤨 Вчера уже не успевал влезть в суть.
Действительно, чудеса.
aspirant:
А как выставить заявку в GUI-примере?
инструменты - выбрать инструмент - новая заявка.
У меня проблема: при попытке выставить заявку в асинхронном режиме выкидывается InvalidCastException в строчке```
plazaMessage.SendAsync2(_connection, timeOut, _messageDispatcher, transaction.Id);
метода PlazaTrader.SendTransaction. Кто-нибудь сталкивался? В синхронном режиме приходит сообшение, что не хватает средств на счете, который действительно пуст. Его нужно пополнять? Если да, то каким образом?
aspirant:
А как выставить заявку в GUI-примере?
инструменты - выбрать инструмент - новая заявка.
У меня проблема: при попытке выставить заявку в асинхронном режиме выкидывается InvalidCastException в строчке```
plazaMessage.SendAsync2(_connection, timeOut, _messageDispatcher, transaction.Id);
> метода PlazaTrader.SendTransaction. Кто-нибудь сталкивался? В синхронном режиме приходит сообшение, что не хватает средств на счете, который действительно пуст. Его нужно пополнять? Если да, то каким образом?
Кстати да, надо не забыть разобраться с тем, как получать вменяемые ошибки в асинхронном режиме.
Залил изменения, чтобы получать инфу по заявкам. Вкратце, использовали не те потоки.
Может уже пора бету выкладывать?
Comments (43)
Login or Create account, Log in or register to leave a comment
Готово
Прочитал. Не понял насчет интенсивности вызова этого метода. Я могу какое-то сообщение пропустить, если не успею вызвать метод ProcessMessage? Или они где-то копяться? С чем тогда прикол этого метода? Почему нельзя просто подписаться на событие и получать данные через него?
Меня еще смутил параметр PollInterval, который передавался в ProcessMessage. Прочитал доку, оказалось что это не PollInterval, а PollTimeout. Стало понятнее. Я так понял, это то время, на которое будет заблокирован метод ProcessMessage, если не будет нового сообщения?
Видел интерфейс IP2MessageReceiver? Я вот думаю, а это случайно не альтернатива ProcessMessage, только без вечного цикла?
Как тебе будет виднее. Но R# говорит, что PlazaSchemaParser все же используется. И, судя по коду, PlazaTableSerializer пишет ini схемы, а PlazaSchemaParser читает. А нам вроде бы и то и другое нужно для работы.
Давай оставим.
Алгоритм подписки на потоки брал из примера плазовцев. Там этот метод вызывается в отдельном thread'е в непрерывном цикле. Во вторник попробую закомментить вызов этого метода и посмотреть, идут ли данные из потоков. Почему они так сделали, мне тоже непонятно.
Да, это так.
В доке как-то все размыто написано. У меня создалось впечатление, что этот интерфейс не относится к данным из потоков. Он нужен для отправки заявок и т.д., а я в это не влезал вообще.
Да, забыл. PlazaSchemaParser используется для десериализации данных из ini-файлов. Но эта фича нам пока не нужна, поэтому предлагаю вместо вызовов PlazaSchemaParser пока выкидывать NotImplementedException()?
Смотрел. Небольшой ликбез по работе пула потоков. В пул потоков мы помещаем небольшие действия, которых может быть очень много, но при этом отрабатывают они быстро. У тебя же помещается вечный цикл, что не является быстрой отработкой.
Идея работы пула в рамках PlazaStreamManager мне видется в заведении таймера (который Threading.Timer, потому что он основан на пуле потоков), в обработчике которого будут перебираться все соединения, и для них будет вызываться ProcessMessage. Тоесть, как только один "зависнет" в ожидании сообщения, таймер создаст еще один пуловый поток, который будет обрабатывать следующее свободное соединение (иначе все потоки будут ждать одно и то же соединение).
Насчет Threadpool'а знаю. Именно из-за этого изначально создавал полноценные Thread'ы.
У меня здесь вот какое предложение. Сейчас мы для каждого стрима создаем отдельный Connection. А что если мы пойдем по более простому пути, как в примере у плазовцев: все стримы используют один Connection. В этом случае создается только один Thread, внутри которого в бесконечном цикле вызвается ProcessMessage. Если будут тормоза, тогда уже будем делать, как ты предлагаешь. Напиши, что думаешь.
С этого и нужно было начать.🙂
Залил, на неделе нужно тестировать.
Исправил код. У тебя там хитрая логика с остановкой и перезапуском потока была, которая по сути не нужно вообще. Ну что это за робот, которому потоки не нужно?🙂 Поток пуская живет все время и закрывается при закрытие PlazaTrader. Меньше сложностей, меньша багов.
Вообще да. Как минимум, системные всегда будут.
Залил
Можешь первый таск добить?
Тестировал, потоки идут, стаканы есть. Без ProcessMessage, кстати, не работает.
Постараюсь завтра-послезавтра
как же вы 4 месяца занимались Плазой и только теперь выясняете, что такое ProcessMessage? судя по техническому форуму РТС, без ясного понимания, как это работает, легко получить тормозящий код. проконсультируйтесь с Кукушкиным, который вроде хорошо разобрался. Или с ртс-овцами. Дока там ужасная.
Вот, кстати, интересная ветка.
Или я не понимаю схему работы сообщений от Плазы, или там обсуждается какая-то ерунда. Таймаут надо ставить по максимуму, так как он дает возможность не вызывать в холостую метод ProcessMessage. Ставить 1 милилсекунду нет никакого смысла, так как данные от Плазы накапливаются (это я так думаю), и все равно ничего не пропустится.
Вот и возник вопрос. Есть сообщения копяться от Плазы, зачем тогда вообще вызывать ProcessMessage? Почему не сделали просто вызов события?
Не знаю, но без вызова точно не работает. Только что еще раз проверил.
=) Я верю что не работает. С первого раза поверил. Но думаю тут не спроста. Или косяк в архитектуре Плазы (не удивлюсь) или мы что-то упустили.
Мне все-таки кажется, что первое. Повторюсь: алгоритм взят из их примера BaselessClient.
ProcessMessage это прокачка очереди сообщений на сокете "вручную". Почему сделано так, а не иначе хз. Для совместимости чего-то с чем-то. Без понимания всех нюансов (а их там много) может быть плохо, потому что внутри есть критические секции, при работе с одним объектом из разных тредов может происходить маршаллинг. Общее правило кажется(!) один поток - один объект коннекшн.
Это как бы правило МТА. Только все равно не понятно насчет ProcessMessage.
Почему в прошедшем времени?🙂
Хорошо, перед сертификацией PlazaTrader обязательно пройдем сертификацию Кукушкина.🙂
Залил заявки. Посмотри в PlazaTrader OnDealFutureStreamInserted / OnDealOptionStreamInserted. В GUI клиенте идут.
По-моему это не заявки.🙂
Это были сделки (deal - Журнал сделок), спешил в ночи😢
Там код получился один в один для фьючей и опцов. Может имеет смысл вынести в общий метод, как я с инструментами сделал? Или как со стаканами.
Удалил это, так как это неправильно.
Статический конструктор есть всегда. Он или нами явно определяется, или его компилятор "дописывает".
Посмотрел и поправил код. Но у меня почему то заявки не идут с Плазы. Выставил по рынку - ни одного уведомления. Перезапустил прогу, опять ничего по заявкам.
static PlazaColumnRegistry() { // Без этого конструктора клиенту нельзя добавить колонки. }
PlazaTableRegistry.DealFuture.Columns.Add(PlazaColumnRegistry.DealFuture.BuyRtsCode);
инструменты - выбрать инструмент - новая заявка.
PlazaTableRegistry.DealFuture.Columns.Add(PlazaColumnRegistry.DealFuture.BuyRtsCode);
У меня проблема: при попытке выставить заявку в асинхронном режиме выкидывается InvalidCastException в строчке``` plazaMessage.SendAsync2(_connection, timeOut, _messageDispatcher, transaction.Id);
еще добавлю, что со сборкой стакана тоже есть ряд тонких моментов. Они вроде описаны в топике
Да, я писал реализацию на основе этого топика.