В чем разница между Invoking и BeginInvoking MessageBox?
В форме сравните
BeginInvoke (new Action (() => {
MessageBox.Show ());
}));
с
Invoke (new Action (() => {
MessageBox.Show ());
}));
В чем разница, и когда я должен использовать один над другим? Каково поведение, вызванное насосом сообщений MessageBox?
Я провел некоторое тестирование и обнаружил, что оба метода блокируют пользовательский интерфейс.
Единственное различие заключается в том, что Invoke фактически вызывается мгновенно, а BeginInvoke занимает (очень короткое) время, пока код не будет запущен. Этого следует ожидать.
Ответы
Ответ 1
BeginInvoke
будет вызывать делегат асинхронно, возвращаясь сразу же, поставив делегат в очередь независимо от текущего потока.
Invoke
будет вызывать делегат синхронно, блокируя вызывающий поток до тех пор, пока делегат не завершит.
Чтобы увидеть разницу, попробуйте следующий код:
BeginInvoke(new Action(()=>Console.WriteLine("BeginInvoke")));
Console.WriteLine("AfterBeginInvokeCalled");
Invoke(new Action(()=>Console.WriteLine("Invoke")));
Console.WriteLine("AfterInvokeCalled");
Вы должны увидеть результат, похожий на следующий, где текст "BeginInvoke" задерживается из-за его асинхронного выполнения:
AfterBeginInvokeCalled
Призовите
AfterInvokeCalled
BeginInvoke
Относительно поведения, которое вы наблюдаете, поскольку это только акт вызова делегата, который является синхронным или асинхронным; содержание метода может привести к остановке вызывающего потока или блокированию пользовательского интерфейса. В случае показа окна сообщения, независимо от того, задерживается ли делегат с помощью BeginInvoke
или нет, после вызова делегата пользовательский интерфейс будет заблокирован до тех пор, пока окно сообщения не будет отклонено.
Ответ 2
Саймон на самом деле не ошибается.
BeginInvoke
походит на отправку сообщения в поток пользовательского интерфейса и говорит: "Сделайте это, как только получите шанс".
Invoke
- это как сказать: "Сделайте это прямо сейчас. Я подожду."
Разъяснение: только потому, что вы расскажите поток пользовательского интерфейса, "сделайте это прямо сейчас", это не значит, что вы являетесь Богом потока пользовательского интерфейса и можете заставить его отказаться от всего, что он делает. В основном, ключевые слова в приведенном выше заявлении: "Я подожду".
Дело в том, что в вашем примере кода сообщение, которое вы отправляете в поток пользовательского интерфейса, это: call MessageBox.Show
. Угадай, что? Это будет блокировать поток пользовательского интерфейса в любом случае.
Если вы хотите заметить асинхронное поведение BeginInvoke
, вызовите его из отдельного потока, поместите точку останова после вызова BeginInvoke
в свой код и обратите внимание, что точка останова попадает даже тогда, когда отображается окно сообщения (и пользовательский интерфейс заблокирован). Если вы вызываете Invoke
, код не будет продолжаться до тех пор, пока пользователь не отклонит окно сообщения.
Ответ 3
BeginInvoke является асинхронным... это означает, что вызывающий поток не будет ждать возврата вызываемого метода.
Итак, диалоговое окно всегда зависает от графического интерфейса. Но разница между begin invoke и invoke должна быть ясна:
Invoke ожидает, что вызванный метод вернется
BeginInvoke не делает.
Ответ 4
Хотя большинство ответов являются технически правильными, они не задают очевидный вопрос.
Почему вы хотите сначала обернуть вызовы MessageBox() в Invoke/BeginOnvoke?
В этой ситуации просто нет пользы в использовании BeginInvoke или Invoke, как объяснил Джефф.
Похоже, вы сбиты с толку между использованием Invoke/BeginInvoke в форме/управлении Windows в многопоточной ситуации и использованием Invoke/BeginInvoke на экземпляре делегата (например, Asynchornous Programming Model).
Это легко сделать, поскольку имена, очевидно, идентичны, однако сценарии, которые вы использовали бы их, и их поведение различны.
Книга CLR Via С# дает хорошее объяснение обоих типов Invoke/BeginInvoke.
Ответ 5
Для MessageBox.Show вопрос в основном не имеет значения.
Единственное различие заключается в том, что с BeginInvoke сам вызывающий поток не будет блокироваться, поэтому он может продолжать делать вещи (очистка, дальнейшая обработка и т.д.).
Поток пользовательского интерфейса, очевидно, блокируется, потому что там появляется модальное окно, ожидающее ввода пользователя, чтобы закрыть его.