В чем разница между Invoke() и BeginInvoke()
просто интересно, в чем разница между BeginInvoke() и Invoke() есть?
В основном то, что каждый из них будет использоваться для.
EDIT: в чем разница между созданием объекта threading и вызовом invoke на этом и просто вызовом BeginInvoke() на делегата? или это одно и то же?
6 ответов:
Вы имеете в виду делегат.Invoke / BeginInvoke или Control.Invoke / BeginInvoke?
- делегат.Вызова: выполняется синхронно, в одном потоке.
- делегат.BeginInvoke: выполняется асинхронно, в потоке threadpool.
- управление.Invoke: выполняется в потоке пользовательского интерфейса, но вызывающий поток ожидает завершения перед продолжением.
- управление.BeginInvoke: выполняется в потоке пользовательского интерфейса, и вызывающий поток не ждет завершение.
ответ Тима упоминает, когда вы можете использовать BeginInvoke-хотя он был в основном ориентирован на делегирование.Начинайте, я подозреваю.
для приложений Windows Forms я бы предложил вам обычно использовать BeginInvoke. Таким образом, вам не нужно беспокоиться о тупике, например, - но вы должны понимать, что пользовательский интерфейс, возможно, не был обновлен к тому времени, когда вы в следующий раз посмотрите на него! В частности, вы не должны изменять данные, которые поток пользовательского интерфейса может использоваться для отображения. Например, если у вас есть человек со свойствами FirstName и LastName, и вы сделали:
person.FirstName = "Kevin"; // person is a shared reference person.LastName = "Spacey"; control.BeginInvoke(UpdateName); person.FirstName = "Keyser"; person.LastName = "Soze";тогда пользовательский интерфейс вполне может в конечном итоге отображать "Keyser Spacey". (Есть внешний шанс, что он может отображать "Kevin Soze", но только через странность модели памяти.)
Если у вас нет такого рода проблемы, однако, контроль.BeginInvoke легче получить право, и позволит избежать фонового потока от необходимости ждать без веской причины. Обратите внимание, что команда Windows Forms гарантирует, что вы можете использовать элемент управления.BeginInvoke в" огонь и забыть " манере-т. е. никогда не вызывая EndInvoke. Это не относится к асинхронным вызовам вообще: обычно каждый BeginXXX должен иметь соответствующий вызов EndXXX, обычно в обратном вызове.
основываясь на ответе Джона Скита, есть моменты, когда вы хотите вызвать делегат и дождаться завершения его выполнения, Прежде чем текущий поток продолжится. В этих случаях вызов Invoke - это то, что вы хотите.
в многопоточных приложениях вы можете не хотеть, чтобы поток ждал делегата для завершения выполнения, особенно если этот делегат выполняет ввод-вывод (что может сделать делегат и ваш блок потока).
в этих случаях BeginInvoke было бы полезно. Вызывая его, вы говорите делегату начать, но тогда ваш поток свободен делать другие вещи параллельно с делегатом.
использование BeginInvoke увеличивает сложность вашего кода, но бывают случаи, когда улучшенная производительность стоит сложности.
разницу между
Control.Invoke()иControl.BeginInvoke()есть
BeginInvoke()запланирует асинхронное действие в потоке GUI. Когда асинхронное действие запланировано, код продолжается. Через некоторое время (вы не знаете точно, когда) ваше асинхронное действие будет выполненоInvoke()выполнит ваше асинхронное действие (в потоке GUI) и дождется завершения вашего действия.логичный вывод заключается в том, что делегат вы переходите к
Invoke()может иметь out-параметры или возвращаемое значение, в то время как делегат вы передаете вBeginInvoke()не может (вы должны использовать EndInvoke для получения результатов).
просто чтобы дать короткий, рабочий пример, чтобы увидеть эффект их разницы
new Thread(foo).Start(); private void foo() { this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate() { myTextBox.Text = "bing"; Thread.Sleep(TimeSpan.FromSeconds(3)); }); MessageBox.Show("done"); }при использовании BeginInvoke, MessageBox появляется одновременно с обновлением текста. Если использовать вызов, MessageBox появляется после 3-секундного сна. Следовательно, показывая эффект асинхронного (BeginInvoke) и синхронной (вызов) звонок.
делегат.BeginInvoke () асинхронно ставит в очередь вызов делегата и немедленно возвращает элемент управления. При использовании делегата.Метод BeginInvoke(), вы должны вызвать делегат.EndInvoke () в методе обратного вызова для получения результатов.
делегат.Invoke () синхронно вызывает делегат в том же потоке.
просто добавляя, почему и когда использовать Invoke().
Как Invoke (), так и BeginInvoke () маршалируют указанный код в поток диспетчера.
но в отличие от BeginInvoke (), Invoke () останавливает поток, пока диспетчер не выполнит ваш код. вы можете использовать Invoke (), если вам нужно приостановить асинхронную операцию, пока пользователь не предоставит какую-либо обратную связь.
например, вы можете вызвать Invoke() для запуска фрагмента кода, который показывает диалоговое окно ОК / отмена. После того, как пользователь нажмет кнопку и ваш маршалированный код завершится, метод invoke() вернется, и вы можете действовать на ответ пользователя.
см. Pro WPF в C# глава 31
Comments