Когда асинхронные делегаты должны использовать шаблон обратного вызова? - PullRequest
3 голосов
/ 28 февраля 2010

Одним из шаблонов, используемых с асинхронными делегатами, является также шаблон обратного вызова, в котором начальный поток (тот, который вызвал BeginInvoke) T1 продолжается без ожидания или проверки, завершился ли созданный поток T2. Вместо этого, когда T2 завершен, T2 вызывает метод обратного вызова, который обрабатывает результаты, вызывает EndInvoke и сообщает T1, что задача завершена.

a) Если метод обратного вызова должен сообщать T1 о завершении задачи, то почему этот метод обратного вызова не вызывается внутри T1, а не в T2?

2) Существует ли какая-то стандартная схема, согласно которой метод обратного вызова должен сообщать T1 о завершении T2?

3) Следует ли использовать шаблон обратного вызова, даже когда T1 должен получить возвращаемое значение асинхронно вызванного метода?

1009 * спасибо *

Ответы [ 2 ]

3 голосов
/ 28 февраля 2010

Позволить потоку запускать код в другом потоке довольно нетривиально. Но это общее требование для приложений Windows Forms и WPF, компоненты пользовательского интерфейса никогда не являются поточно-ориентированными. Они do имеют общий шаблон для этого, соответственно методы Control.Invoke и Dispatcher.Invoke. И есть стандартный вспомогательный класс, BackgroundWorker. Он вызывает события в потоке пользовательского интерфейса, его аналогом для метода обратного вызова является событие RunWorkerCompleted.

Вы, конечно, можете вращать свой собственный механизм, если предпочитаете использовать метод BeginInvoke () делегата, но получить это право может быть сложно.

3 голосов
/ 28 февраля 2010
  • почему метод обратного вызова не вызывается в T1?

Как правило, это невозможно; если T1 выключен для выполнения какой-либо другой работы, невозможно выполнить маршалинг обратно к нему, если только у потока уже нет механизма для публикации и планирования работы над ним (например, поток пользовательского интерфейса через SynchronizationContext).

  • существует ли стандартная схема уведомления о многопоточности?

Я бы сказал нет; Существует несколько шаблонов синхронизации между потоками, каждый из которых применяется к различным целевым сценариям.

  • что если T1 нужно возвращаемое значение?

Если T1 нужно возвращаемое значение в текущем стеке, то в конечном итоге ему придется заблокировать, чтобы получить его. Блокировка может произойти путем вызова EndInvoke, использования WaitHandle или других стратегий из предыдущего пункта.

Если вещь, которой нужно возвращаемое значение, это «просто поток» (например, поток пользовательского интерфейса), но не в определенном контексте стека / вызова, то обычно SynchronizationContext.Post или Dispatcher.Invoke используется для маршалинга работы, которая в конечном итоге возвращается назад. в поток пользовательского интерфейса, как только он будет готов.

...