| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Общие вопросы по .NET и C# > Как идет обработка одновременных событий? |
| Автор: dAlex 21.2.2011, 14:06 |
| Проблема такая. У меня есть биржевой робот, который, грубо говоря, реагирует на событие "произошла сделка" и далее есть функция обработки. В зависимости от того, какая была сделка, следующая сделка может обрабатываться по-разному. Но иногда бывает так, что одновременно происходят 2 сделки. Что происходит в таком случае с их обработкой? возникает ли какая-то очередь событий? Или обработка двух событий происходит одновременно в разных потоках? |
| Автор: dAlex 21.2.2011, 14:42 | ||||
| робот узнает по ссылке из DDE. не знаю, как оно там =) робот-то мой, обработка событий происходит просто "подпиской" на событие, такого плана
просто для меня и так было открытием узнать, что нельзя выводить данные одновременно с отрисовкой интерфейса, и что в таком случае надо делать BeginInvoke. Возможно, тут еще что-то такое upd: в функции обработки у меня пишется лог в файл. Добавила там первой строчкой запись строки типа "идет обработка сделки такой-то". Сейчас наблюдаю в логе 2 таких строчки подряд, то есть как-то одновременно обработка 2х сделок-событий происходит Добавлено @ 14:50 вот блин! сама уже не разбираюсь в своем коде. Вот так идет обработка сделок
AddDataByNewTrade и есть функция обработки сделки то есть это и есть разные потоки? или как? |
| Автор: -Mikle- 21.2.2011, 15:11 |
| Ну видимо одновременно все таки... Ставьте lock на выполнение кода в событии или что-нить подобное для синхронизации потоков. А вообще, если к вам приходит что-то в многопоточном режиме, то надо либо быть уверенным что интервал между посылками (в среднем) будет достаточный для того чтоб код отработал, либо надо тогда уже придерживаться многопоточной среды до конца. Например: идут асинхронные посылки с средним интервалом 100мс (в среднем имеется ввиду что могут например прийти две посылки одновременно, а потом до следующей например пройдет 200мс). Если код обработки посылок (ЗАВЕДОМО(!)) выполняется не более 50-70мс, то можно ставить тогда все эти посылки в очередь на выполнение в одном потоке. Если нет, то однозначно будет образовываться очередь, которая приведет в итоге к краху приложения. В последнем случае, надо очень быстро ложить посылки в очередь и отпускать блокировку сразу после этого. А далее, разгребать эту очередь используя пул потоков. Если сообщение на вершине очереди лежит например 1 сек, то пулер должен натравить еще один поток на эту же самую очередь. И наоборот, если поток в пулуре простаивает в течение какого-то периода, то надо убить поток сэкономив тем самым ресурсы процессора. |
| Автор: dAlex 21.2.2011, 15:27 | ||
а как это делается? |
| Автор: -Mikle- 21.2.2011, 18:17 | ||
До тех пор пока выполняется код внутри lock ни один другой поток не зайдет внутрь. Они все будут стоять в очереди (схематично можно считать, что все они будут стоять на строчке lock). Как только выполнение кода завершится одним потоком, другой (один) поток войдет внутрь, остальные будут продолжать стоять. Имейте ввиду, что очередь в данном смысле, не означает соблюдение очередности пришедших потоков. Например, потоки могут прийти в порядке 1,2,3,4, но выполнятся могут в порядке 1,4,3,2. В данном случае, этот порядок не контролируем и в большинстве случаев, нет необходимости его как-либо контролировать. Подробнее про все это можно найти на MSDN и просторах интернета. PS: Помните, что вы не обязаны блокировать весь метод целиком. Вы можете заблокировать только часть кода. PPS: Про синхронизацию потоков это еще не все, существует целая масса средств для многопоточных приложений, позволяющих выполнять потоковую синхронизацию, мониторинг, ограничения и прочие связанные вещи. |
| Автор: dAlex 22.2.2011, 10:48 |
| -Mikle-, спасибо =) читаю в мсдне сейчас про это. Но не знаю, какой мне объект указывать для блокировки? |
| Автор: -Mikle- 22.2.2011, 13:29 | ||
Вообще любой, но обычно на практике для каждого блокируемого кода создают просто обжект. Имеется ввиду для каджого логически блокируемого кода. Предположим, у вас есть тре метода, которые производят какие-то операции с одной коллекцией и необходимо, чтобы имелся многопоточный доступ к этим трем методам. В этом случае, объект блокировки для всех частей кода который работает с коллекцией будет один. Можно использовать саму коллекцию в качестве инстанса блокировки, но как я уже сказал, лучше создать отдельный экземпляр класса object, например так:
|
| Автор: dAlex 22.2.2011, 15:48 |
| -Mikle-, сделала так, как вы сказали =) на первый взгляд вроде правильно работает, даже отрисовка интерфейса притормаживает, когда обработка идет, но надо еще тестить. |
| Автор: Экскалупатор 22.2.2011, 16:25 |
а почему притормаживает? у тебя же все в отдельном потоке работает. |
| Автор: -Mikle- 22.2.2011, 17:57 | ||
Я полагаю, что dAlex весь код обработки посылки охватила методом Invoke. dAlex, если я прав, то необходимо исправить это, охватив методом Invoke только те части кода, которые непосредственно обновляют окно. Иначе, пропадает какой либо смысл в многопоточности, так как отдельный поток в таком случае, просто передает всю работу основному потоку, а сам просто сидит на паузе и ждет завершения. Если будут проблемы с этим, создавайте отдельную тему и если не я, то кто-то еще вам обязательно помогут. Удачи вам в освоении асинхронных взаимоотношений Добавлено через 2 минуты и 54 секунды А вообще, стремление должно быть к тому, чтоб максимально возможно избегать обновления интерфейса из другого потока (насколько это возможно и насколько это позволит дотошный пользователь вашего приложения |
| Автор: dAlex 24.2.2011, 10:22 |
| -Mikle-, так смысл как раз в том, чтобы одновременно коллекции данных менял только один поток =) а как раз при обновлении коллекций обновляется окно, они забиндены с листбоксами =) Добавлено через 1 минуту и 19 секунд а пользователю пофигу, лишь бы правильно работало, да побыстрее Добавлено через 13 минут и 40 секунд хотя нет, вот сейчас по логу снова проскочило две одновременных обработки - или не стоит судить по логу? лог пишется участками, но внутри lock |
| Автор: dAlex 24.2.2011, 12:37 |
| или все-таки это не одновременная обработка, а происходит выход из функции в самом начале, из-за одной штуки, надо проверить... |
| Автор: dAlex 24.2.2011, 13:46 | ||
| там, оказывается, иногда эксепшн вылезал, так что это не одновременная обработка была, а просто быстрый выход из нее =) значит, работает =) спасибо всем за помощь =) Добавлено через 2 минуты и 15 секунд
Ох, спасибо =) вот так всегда, по закону подлости - что-то совершенно новое и довольно объемное попадается именно тогда, когда нет времени это нормально рассмотреть и реализовать =) |
| Автор: -Mikle- 24.2.2011, 21:31 | ||
Это обычное дело для многих я думаю, я к таким вещам уже привык |
| Автор: dAlex 24.2.2011, 22:19 |
| -Mikle-, обязательно =) я и не ухожу |