Invoke и BeginInvoke - PullRequest
       35

Invoke и BeginInvoke

16 голосов
/ 15 декабря 2009

Привет, Я разрабатываю какое-то приложение на C #. На данный момент я имею дело с потоками, и у меня есть вопрос, который у меня в голове. В чем разница между Invoke и BeginInvoke? Я прочитал какую-то ветку и нашел здесь полезную информацию: здесь

Однако в чем разница между Invoke и BeginInvoke в следующем коде:

private void ProcessRoutine()
{
   for (int nValue = StartFrom; nValue <= EndTo; nValue++)
   {
      this.Invoke(this.MyDelegate, nValue);
      //this.BeginInvoke(this.MyDelegate, nValue);
   }
   MessageBox.Show("Counting complete!");
}
private void MessageHandler(int progress)
{
    lblStatus.Text = lblStatus.Text = "Processing item: " + progress.ToString();
    progressBar1.Value = progress;
}

где MyDelegate - ссылка на функцию MessageHandler.

Я заметил, что при использовании BeginInvoke lblStatus.Text не обновляется, когда при использовании Invoke обновляется метка. Кроме того, я знаю, что Invoke ожидает завершения выполнения. Самый важный случай, который меня интересует, заключается в том, почему в этом случае есть разница в обновлении текста метки.

Ответы [ 5 ]

19 голосов
/ 15 декабря 2009

Для начала по вашей ссылке:

  • Control.Invoke: выполняется в потоке пользовательского интерфейса, но вызывающий поток ожидает завершения, прежде чем продолжить.
  • Control.BeginInvoke: выполняется васинхронный поток пользовательского интерфейса и вызывающий поток не ждут завершения.

и из MSDN:

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

Подводя итог, BeginInvoke является асинхронным .Когда BeginInvoke вызывается из потока пользовательского интерфейса, запрос будет выполняться параллельно с потоком пользовательского интерфейса.Это означает, что он может не выполняться до тех пор, пока не будет возвращен текущий выполняемый метод.Таким образом, в этом случае текстовое поле никогда не появится для обновления, поскольку цикл for не будет прерван, поскольку вызывающий поток не будет ожидать завершения этого события, прежде чем продолжить.

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

7 голосов
/ 15 декабря 2009

С помощью Invoke метод выполняется, и приложение ожидает его завершения.

При использовании BeginInvoke метод вызывается асинхронно, и приложение продолжает выполняться, пока выполняется метод, указанный в BeginInvoke.

С BeginInvoke вам нужно вызвать EndInvoke, чтобы получить результаты метода, который вы выполнили с помощью BeginIvnoke.

Не следует обновлять компоненты графического интерфейса в методах BeginXXX, поскольку они запускаются в другом потоке в поток графического интерфейса, в отличие от вашего метода Invoke. Вы не можете получить доступ к компонентам GUI в другом потоке к потоку GUI.

Надеюсь, это поможет!

5 голосов
/ 10 февраля 2010

Control.BeginInvoke не работает в другом потоке (или пуле потоков), как делегат.BeginInvoke. Один вкладыш MSDN говорит:

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

Однако Control.BeginInvoke просто использует PostMessage и возвращает - CLR Thread не создается.

Функция PostMessage размещает (сообщения) сообщение в очереди сообщений связано с темой, которая создал указанное окно и возвращается без ожидания потока обработать сообщение.

В этой статье обобщено, достаточно ли хорошо использовать Invoke или BeginInvoke:

Какую функцию использовать, спросите вы. Это действительно зависит от вашего требования. Если Вы хотите, чтобы обновление пользовательского интерфейса завершилось прежде чем продолжить, вы используете Invoke. Если нет такого требования, я бы предложить использовать BeginInvoke, так как он делает нить, вызывающая это, казалось бы, "Быстрее". Есть несколько ошибок Гоча хотя с BeginInvoke.

  • Если функция, которую вы вызываете через BeginInvoke, получает доступ к общему состоянию (состояние совместно используется потоком пользовательского интерфейса и другие темы), вы в беда. Государство может измениться между звонком BeginInvoke и когда завернутый функция фактически выполняется, что приводит к трудно найти проблемы со временем.
  • Если вы передаете опорные параметры в функцию, вызываемую через BeginInvoke, то вы должны убедиться, что никто не изменяет переданный объект до завершения функции. Обычно люди клонируют объект перед передачей его в BeginInvoke, что позволяет полностью избежать этой проблемы.
1 голос
/ 15 декабря 2009

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

0 голосов
/ 15 декабря 2009

Это в основном сводится к тому, хотите ли вы, чтобы элемент управления обновлялся синхронно или асинхронно. Все зависит от вашей конкретной ситуации.

...