Ситуация такая: есть рабочий поток, производящий некие действия, которые могут вызывать события (в терминах .NET, по-англ., очевидно, "firе events"). События должны вызывать изменения в UI, который живёт в основном потоке. Можно ли просто написать обработчик этих событий, возбуждаемых в другом потоке и дёргать из него UI компоненты или же надо действовать как-то иначе?
27.05.09 16:42: Перенесено модератором из '.NET' — TK
Здравствуйте, <Аноним>, Вы писали:
А>Ситуация такая: есть рабочий поток, производящий некие действия, которые могут вызывать события (в терминах .NET, по-англ., очевидно, "firе events"). События должны вызывать изменения в UI, который живёт в основном потоке. Можно ли просто написать обработчик этих событий, возбуждаемых в другом потоке и дёргать из него UI компоненты или же надо действовать как-то иначе?
Вам надо вызывать события в контексте ui-потока.
Есть два основных способа — универсальный через SynchronizationContext (так работает AsyncOperation и BackgroundWorker)
и использовать ISynchronizeInvoke (его реализует Control и всё что от него унаследовано).
Принцип одинаков — вам надо получить контекст/контрол в исходном потоке и вызывать в рабочем
context.Post(o=>CallEvent(someparams),o); //если хотим чтобы поток ждал выполнения CallEvent - заменяем Post на Send.
// -или-
synchronizeInvoke.BeginInvoke(new Action(()=>CallEvent(someparams))); // Аналогично - заменяем BeginInvoke на Invoke.
Выделенное жирным будет выполняться в контексте ui-потока.
Сорри, код набиваю прямо здесь, могут быть опечатки.
Здравствуйте, Аноним, Вы писали:
А>Ситуация такая: есть рабочий поток, производящий некие действия, которые могут вызывать события (в терминах .NET, по-англ., очевидно, "firе events"). События должны вызывать изменения в UI, который живёт в основном потоке. Можно ли просто написать обработчик этих событий, возбуждаемых в другом потоке и дёргать из него UI компоненты или же надо действовать как-то иначе?
Напрямую "кидать" события в UI поток нельзя. Можно воспользоваться AsyncOperationsManager который предоставляет интерфейс для передачи событий между двумя произвольными потоками. Можно завести специальную очередь которая будет обрабатываться по событию OnIdle из UI потока
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
проще всего использовать SynchronizationContext. Все .Net GUI framework'и (а их 2 — WinForms и WPF) устанавливают свой контекст синхронизации. Захватите его в UI потоке через статическое свойство Current и используйте для выполнения кода в контексте UI из других потоков при помощи простых методов Post и Send (синхронно и асинхронно по аналогии с Post/SendMessage в Win32).
Здравствуйте, <Аноним>, Вы писали:
А>Ситуация такая: есть рабочий поток, производящий некие действия, которые могут вызывать события (в терминах .NET, по-англ., очевидно, "firе events"). События должны вызывать изменения в UI, который живёт в основном потоке. Можно ли просто написать обработчик этих событий, возбуждаемых в другом потоке и дёргать из него UI компоненты или же надо действовать как-то иначе?
Base Class for Implementing the Event-based Asynchronous Pattern — покопайтесь в исходниках, там всё просто, легко можно добавить свои экзотические собятия. На эти события вызывающий поток может спокойно подписываться и не беспокоиться о том, из какого потока они приходят.
Этот вопрос по-моему с периодичностью в пару недель на RSDN задается
Кстати в таких случаях очень удобно когда автоматически происходит поиск похожих тем по ключевым словам темы при составлении вопроса, типа как на StackOverflow. Жаль на rsdn этого никогда не будет