Должен ли я использовать Invoke или SynchronizationContext для обновления элементов управления формы из другого потока?

Попытка обернуть мою голову вокруг обновления элементов управления пользовательского интерфейса из других потоков.

В настоящее время используется BeginInvoke и, честно говоря, он работает нормально, но я продолжаю слышать о том, как вы можете использовать SynchronizationContext, чтобы сделать то же самое.

Что предпочтительнее?

Кроме того, неудобно ли обновлять пользовательский интерфейс из потока? Было бы лучше поднять событие и иметь основную форму вместо этого или есть другие предпочтительные способы сделать это?

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

Изменить: Также теперь я вижу маршрут TaskScheduler.FromCurrentSynchronizationContext. Так много вариантов x_x

Ответы

Ответ 1

Я предпочитаю SynchronizationContext над Control.Invoke. Опасность Control.Invoke заключается в том, что существует проблема с временем существования Control. Если элемент управления находится во время попытки Invoke на нем, то он ставит под угрозу способность вызова к успеху. Это происходит, когда диалоги закрыты, сдвинутые представления и т.д.

SynchronizationContext.Current хотя обычно живет так долго, как связанный с ним поток. Он имеет конечное время жизни и, следовательно, в конечном итоге те же проблемы, но он несколько более предсказуем, чем a Control.

Ответ 2

Изучали ли вы использование компонента Background Worker? Для длительных задач, которые не должны связывать пользовательский интерфейс, это чистый и простой способ получения многопоточных возможностей. Например, вы можете выполнять обновления в пользовательском интерфейсе с помощью события ProgressChanged и рабочего фона, а класс рабочего класса будет гарантировать, что поток, создавший BW, является тем, который выполняет событие ProcessChanged и WorkComplete. Поэтому, если вы сделали BW из пользовательского интерфейса и настроили его на работу, вы можете безопасно обновить интерфейс.

Вот краткая статья от MS http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx

Еще одна действительно хорошая ссылка http://www.albahari.com/threading/part3.aspx#_BackgroundWorker