Каково различие между Вызовом и BeginInvoking MessageBox?

В форме выдержать сравнение

BeginInvoke (new Action (() => {
    MessageBox.Show ());
}));

с

Invoke (new Action (() => {
    MessageBox.Show ());
}));

Каково различие, и когда я должен использовать один по другому? Как поведение затронуто насосом сообщения MessageBox?

Я сделал некоторое тестирование и нашел, что оба метода блокируют UI.

Единственная разница, это Вызывает, на самом деле назван немедленно, в то время как BeginInvoke занимает (очень короткое) время, пока код не выполняется. Это должно ожидаться.

12
задан mafu 12 May 2010 в 13:33
поделиться

5 ответов

BeginInvoke вызовет делегат асинхронно, возвращаясь немедленно, поставив делегат в очередь на выполнение независимо от текущего потока.

Invoke вызовет делегата синхронно, блокируя вызывающий поток до завершения работы делегата.

Чтобы увидеть разницу, попробуйте следующий код:

BeginInvoke(new Action(()=>Console.WriteLine("BeginInvoke")));
Console.WriteLine("AfterBeginInvokeCalled");

Invoke(new Action(()=>Console.WriteLine("Invoke")));
Console.WriteLine("AfterInvokeCalled");

Вы должны увидеть вывод, похожий на следующий, где текст "BeginInvoke" отложен из-за его асинхронного выполнения:

AfterBeginInvokeCalled
Invoke
AfterInvokeCalled
BeginInvoke

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

16
ответ дан 2 December 2019 в 04:08
поделиться

На самом деле Саймон не ошибся.

BeginInvoke подобен отправке сообщения в поток пользовательского интерфейса со словами: «Сделайте это, как только представится возможность».

Invoke - это как сказать: «Сделайте это прямо сейчас . Я подожду ».

Уточнение: только то, что вы говорите потоку пользовательского интерфейса:« Сделайте это прямо сейчас », это не означает, что вы являетесь Богом потока пользовательского интерфейса и можете заставить его бросить все, что он делает. По сути, ключевые слова в приведенном выше утверждении - «Я буду ждать».

Дело в том, что в вашем примере кода сообщение, которое вы отправляете потоку пользовательского интерфейса, выглядит следующим образом: call MessageBox.Show . Угадай, что? В любом случае это заблокирует поток пользовательского интерфейса.

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

14
ответ дан 2 December 2019 в 04:08
поделиться

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

Итак, диалоговое окно всегда замораживает GUI. Но разница между begin invoke и invoke теперь должна быть ясна:

Invoke ждет возвращения вызванного метода. BeginInvoke этого не делает.

3
ответ дан 2 December 2019 в 04:08
поделиться

Для MessageBox.Show вопрос в основном неуместен.

Единственное отличие состоит в том, что с BeginInvoke сам вызывающий поток не будет блокироваться, поэтому он может продолжать выполнять какие-то действия (очистку, дальнейшую обработку и т. Д.).

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

1
ответ дан 2 December 2019 в 04:08
поделиться

Хотя большинство ответов технически верны, они не задают очевидного вопроса.

Почему вы вообще хотите заключать вызовы MessageBox () в Invoke / BeginOnvoke?

Как объяснил Джефф, использование BeginInvoke или Invoke в этой ситуации просто бесполезно.

Похоже, вы запутались между использованием Invoke / BeginInvoke в форме / элементе управления Windows в многопоточной ситуации и использованием Invoke / BeginInvoke в экземпляре делегата (то есть в модели асинхронного программирования).

Это легко сделать, поскольку имена явно идентичны, однако сценарии их использования и их поведение различаются.

Книга CLR Via C # дает хорошее объяснение обоих типов Invoke / BeginInvoke.

2
ответ дан 2 December 2019 в 04:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: