Библиотека S# вызывает событие ProcessDataError синхронно.
Atom Ответить
06.10.2010


Михаил, добрый день.

Экспериментальным путем установил, что пока не закончит работу метод,
который подписан на событие ProcessDataError, остальные события библиотека
не производит. Так же не назначается Id сделке, если сделка была подана
в то время, когда событие ProcessDataError было «подвешено».

Из этого могу предположить, что события из библиотеки вызываются синхронным образом.

Вопросы:
Все ли события вызываются синхронно или только ProcessDataError?
Это баг или фича, и если баг, то будет ли он исправлен (исправлено на асинхронные вызовы)?

Теги:


Спасибо:




6 Ответов
Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 06.10.2010
Ответить


Каждое событие вызывается с своем потоке. Но, например, если событие новых сделок (NewMyTrades) привело к ошибке, то будет вызвано ProcessDataError в том потоке, в котором оно было инициировано. Соответственно, NewMyTrades не будет вызван до тех пор, ка освободиться ProcessDataError. Другие события будут работать.

То, что ID не заполняется - вряд ли. Надо конкретнее разбираться. Потому что все данные накапливаются в очереди, и ничего не теряется. ID сделки - это какое поле вы имеет ввиду (+ какой класс)?
Спасибо:

Maxim

Фотография
Дата: 06.10.2010
Ответить


У меня происходит следующее:

1) Я создаю заявку Order1 в Потоке1.

2) Отменяю Order1 в Потоке1.

3) После отмены заявки срабатывает событие ProcessDataError в Потоке2.
Об этом я писал здесь: Событие BaseTrader.ProcessDataError выдает сообщение о снятии заявки.

4) Событие ProcessDataError вызывает Метод в Потоке2, который ждет определенного условия.
То есть некоторое время не освобождает Поток2.

5) А в это время создается заявка Order2 в Потоке1.
Не смотря на то, что эта заявка появилась в Квике, Id в Order2
остается равным 0. Так же не возникает события NewOrders.


Если в 4 пункте сразу освобождать событие ProcessDataError ,
то в 5 пункте все происходит как обычно: и Id появляется и NewOrders срабатывает.
Автор топика
Спасибо:

Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 06.10.2010
Ответить


Maxim
У меня происходит следующее:

5) А в это время создается заявка Order2 в Потоке1.
Не смотря на то, что эта заявка появилась в Квике, Id в Order2
остается равным 0. Так же не возникает события NewOrders.


Да, так как у Вас событие NewOrders "висит" при первом вызове ProcessDataError, то данные по ДДЕ не обрабатываются по заявкам. Может убрать ожидание в обработчике ошибок?
Спасибо:

Maxim

Фотография
Дата: 06.10.2010
Ответить


Убрать ожидание скорей всего смогу (сделаю свой BeginInvoke).

То есть вышеописанное поведение — нормальное?

Не совсем понял, в каких случаях события вызываются взаимосвязано, а в каких нет?
Если не сложно, можете еще раз пояснить, для более четкого представления?
Почему не вызывать ProcessDataError асинхронно?

Может в мануале сделать раздел FAQ? Что бы Вам туда постить ответы из форума.
Автор топика
Спасибо:

Иванов Андрей

Фотография
Дата: 08.10.2010
Ответить


Maxim
То есть вышеописанное поведение — нормальное?

Нормальное. Ваша ситуация называется deadlock (взаимная блокировка). Увеличение количества активных потоков просто оттянет конец.

Цитата:
Не совсем понял, в каких случаях события вызываются взаимосвязано, а в каких нет?
Если не сложно, можете еще раз пояснить, для более четкого представления?

Закладываться на такие вещи нельзя. Сегодня взаимосвязано что-то одно, завтра что-то другое.
Синхронно пользоваться ивентами (из System.Threading, например, AutoResetEvent) можно только в одном случае -- у вас есть один отдельный поток, созданный вами и который что-то делает в ответ на какие-то события. Во всех остальных случаях нарваться на дедлок очень легко. Что вы и сделали.

Цитата:
Почему не вызывать ProcessDataError асинхронно?

"Асинхронно" и "другой поток" не синонимы. Асинхронно это без блокирования потока на не-CPU операции с неопределённым или большим временем исполнения. Исполнение метода в другом потоке это параллельное исполнение.

С точки зрения обывателя разницы между параллельным исполнением и асинхронным может быть нет. А с точки зрения системы есть. Реальный асинхронный вызов реализуется через IO поток, который ждёт на WaitHandle. Поэтому когда вы якобы асинхронно запускаете исполнение метода через BeginInvoke, и висите там на WaitHandle, вы просто оттягиваете дедлок и прячете его. Где читать рекомендации по пользованию ThreadPool я не знаю, но уверен, что таких мест полно.

Если я не ошибся и вы сидите в обработчике события на WaitHandle, советую обратить внимание не на BeginInvoke, который нужен для запуска CPU-задач, а на RegisterWaitForSingleObject, который как раз и предназначен для асинхронного реагирования на события. То есть, без блокирования активного потока. Если же ошибся, то советую вам перейти на реализацию, которую описал выше, потому что иначе намучаетесь.

Цитата:
Может в мануале сделать раздел FAQ? Что бы Вам туда постить ответы из форума.

Если имеется в виду конкретно данная тема, то в фак стоит добавить ссылку на книгу Рихтера, например. Только кто ж её читать будет -- очень уж длинный фак получается =)
Просто таких вопросов триллиард и они не про S#, а про азы многопоточного программирования.
Спасибо:

Maxim

Фотография
Дата: 12.10.2010
Ответить


Спасибо за ответ.

Насчет многопоточности написано вот здесь хорошо:
http://www.albahari.com/threading/
Автор топика
Спасибо:


Добавить файлы через драг-н-дроп, , или вставить из буфера обмена.

loading
clippy