В чем разница между Invoke() и BeginInvoke()



просто интересно, в чем разница между BeginInvoke() и Invoke() есть?



В основном то, что каждый из них будет использоваться для.



EDIT: в чем разница между созданием объекта threading и вызовом invoke на этом и просто вызовом BeginInvoke() на делегата? или это одно и то же?

665   6  

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 () синхронно вызывает делегат в том же потоке.

статья MSDN

просто добавляя, почему и когда использовать Invoke().

Как Invoke (), так и BeginInvoke () маршалируют указанный код в поток диспетчера.

но в отличие от BeginInvoke (), Invoke () останавливает поток, пока диспетчер не выполнит ваш код. вы можете использовать Invoke (), если вам нужно приостановить асинхронную операцию, пока пользователь не предоставит какую-либо обратную связь.

например, вы можете вызвать Invoke() для запуска фрагмента кода, который показывает диалоговое окно ОК / отмена. После того, как пользователь нажмет кнопку и ваш маршалированный код завершится, метод invoke() вернется, и вы можете действовать на ответ пользователя.

см. Pro WPF в C# глава 31

Comments

    Ничего не найдено.