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

Typedef не является простой текстовой заменой.

typedef const CHARS CPTR;

Означает: «Тип CPTR будет состоять из const CHARS». Но CHARS - это тип указателя на символ, так что это говорит о том, что тип CPTR будет типом const-указателя-символа. Это не соответствует тому, что вы видите при простой замене.

Другими словами,

typedef char * CHARS;

является не таким же, как

#define CHARS char *

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

Вот простой способ выяснить, что объявляет typedef:

  1. Удалить ключевое слово typedef. Теперь у вас будет объявление переменной.
    const CHARS CPTR;
    
  2. Выясните, какой тип этой переменной (некоторые компиляторы имеют оператор typeof(), который делает именно это и очень полезен). Вызовите этот тип T. В этом случае указатель константы на (непостоянный) символ.
  3. Замените typedef. Теперь вы объявляете новый тип (CPTR), который является точно таким же типом, что и T, постоянным указателем на (непостоянный) char.
371
задан ArunPratap 5 March 2019 в 05:11
поделиться

6 ответов

Вы имеете в виду Delegate.Invoke / BeginInvoke или Control.Invoke / BeginInvoke?

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

В ответе Тима упоминается, когда вы, возможно, захотите использовать BeginInvoke - хотя, я подозреваю, он был в основном ориентирован на Delegate.BeginInvoke.

Для приложений Windows Forms я бы посоветовал вам обычно использовать BeginInvoke. Таким образом, вам не нужно беспокоиться о взаимоблокировке, например, - но вы должны понимать, что пользовательский интерфейс, возможно, не был обновлен, когда вы в следующий раз посмотрите на него! В частности, вы не должны изменять данные, которые поток пользовательского интерфейса может использовать для отображения. Например, если у вас есть свойства Person со значениями FirstName и LastName, и вы сделали:

person.FirstName = "Kevin"; // person is a shared reference
person.LastName = "Spacey";
control.BeginInvoke(UpdateName);
person.FirstName = "Keyser";
person.LastName = "Soze";

, тогда пользовательский интерфейс может в конечном итоге отобразить «Keyser Spacey». (Существует внешняя вероятность, что он может отобразить «Кевин Созе», но только из-за странности модели памяти.)

Однако, если у вас нет такой проблемы, Control.BeginInvoke будет проще понять, и будет Избегайте фоновой ветки от необходимости ждать без веской причины. Обратите внимание, что команда Windows Forms гарантировала, что вы можете использовать Control.BeginInvoke в режиме «запускай и забывай», то есть никогда не вызывая EndInvoke. Это не относится к асинхронным вызовам в целом: обычно каждый BeginXXX должен иметь соответствующий вызов EndXXX, обычно в обратном вызове.

536
ответ дан Matthew Groves 5 March 2019 в 05:11
поделиться

Основываясь на ответе Джона Скита, бывают случаи, когда вы хотите вызвать делегата и дождаться его выполнения до завершения текущего потока. В этих случаях вызов Invoke - это то, что вы хотите.

В многопоточных приложениях вам может не потребоваться, чтобы поток ожидал делегата, чтобы завершить выполнение, особенно если этот делегат выполняет ввод / вывод (что может сделать делегат и ваш поток блокированным).

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

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

42
ответ дан Tim Stewart 5 March 2019 в 05:11
поделиться

Разница между Control.Invoke() и Control.BeginInvoke() состоит в том, что

  • BeginInvoke() запланирует асинхронное действие в потоке GUI. Когда запланировано асинхронное действие, ваш код продолжается. Некоторое время спустя (вы точно не знаете, когда) ваше асинхронное действие будет выполнено
  • Invoke() выполнит ваше асинхронное действие (в потоке GUI) и будет ждать, пока ваше действие не будет завершено.

Логический вывод заключается в том, что делегат, который вы передаете в Invoke(), может иметь out-параметры или возвращаемое значение, в то время как делегат, который вы передаете в BeginInvoke(), не может (вы должны использовать EndInvoke для получения результатов ).

24
ответ дан Sujit 5 March 2019 в 05:11
поделиться

Просто для краткого, рабочего примера, чтобы увидеть эффект их различия

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 выскакивает одновременно с обновлением текста. Если использовать Invoke , MessageBox выскакивает после 3-секундного сна. Отсюда показано влияние асинхронного ( BeginInvoke ) и синхронного ( Invoke ) вызова.

15
ответ дан KMC 5 March 2019 в 05:11
поделиться

Delegate.BeginInvoke () асинхронно ставит в очередь вызов делегата и немедленно возвращает управление. При использовании Delegate.BeginInvoke () вы должны вызывать Delegate.EndInvoke () в методе обратного вызова, чтобы получить результаты.

Delegate.Invoke () синхронно вызывает делегата в том же потоке.

MSDN Статья

8
ответ дан Aaron Palmer 5 March 2019 в 05:11
поделиться

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

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

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

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

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

.
7
ответ дан Ingako 5 March 2019 в 05:11
поделиться
Другие вопросы по тегам:

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