Последствия производительности BeginInvoke

Я наследовал код, откуда BeginInvoke называют основного потока (не фоновый поток, который обычно является шаблоном). Я пытаюсь понять то, что это на самом деле делает в этом сценарии.

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

Как платформа располагает по приоритетам, когда начать метод, названный BeginInvoke?

Править: Код похож на это:

System.Action<bool> finalizeUI = delegate(bool open)
{
    try
    {
        // do somewhat time consuming stuff
    }
    finally
    {
        Cursor.Current = Cursors.Default;
    }
};

Cursor.Current = Cursors.WaitCursor;
BeginInvoke(finalizeUI, true);

Это происходит в событии Form_Load.

6
задан AngryHacker 18 March 2010 в 21:28
поделиться

4 ответа

edit

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

Вызов BeginInvoke находится внутри Form_load и не вызывается для другого объекта, поэтому это вызов Form.BeginInvoke. Так вот что происходит.

  1. Form_Load передает делегат Form.BeginInvoke, это помещает сообщение в очередь сообщений формы, которая на опережает всех сообщений, вводимых пользователем. Он устанавливает курсор на курсор ожидания.
  2. Form_Load возвращается, и остальная часть инициализации формы может быть завершена, форма, скорее всего, станет видимой в этот момент.
  3. Как только код попадает в насос сообщений, первое, что видит в очереди, - это делегат, и он его выполняет.
  4. , когда делегат завершает работу, он меняет курсор обратно на нормальный курсор и возвращает
  5. прибыль!

исходное сообщение ниже


Я зависит от объекта, для которого вы вызываете BeginInvoke. Если объект является производным от Control , то Control.BeginInvoke будет выполняться в потоке, создавшем элемент управления. См. Ответ Джаредпара.

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

public class Foo
{
    ...
    public Object Bar(object arg)
    {
       // this function will run on a separate thread.
    }
}

...

// this delegate is used to Invoke Bar on Foo in separate thread, this must
// take the same arguments and return the same value as the Bar method of Foo
public delegate object FooBarCaller (object arg);

...

// call this on the main thread to invoke Foo.Bar on a background thread
//
public IAsyncResult BeginFooBar(AsyncCallback callback, object arg)
{
   Foo foo = new Foo();
   FooBarCaller caller = new FooBarCaller (foo.Bar);
   return caller.BeginInvoke (arg);
}

Этот шаблон является одной из причин того, что BeginInvoke вызывается из основного потока, а не из фонового потока.

4
ответ дан 16 December 2019 в 21:38
поделиться

До повсеместного использования BackgroundWorker вам приходилось выполнять обратную синхронизацию с потоком пользовательского интерфейса, прежде чем выполнять какие-либо операции с элементами управления, созданными в потоке пользовательского интерфейса (т.е. почти каждый элемент управления ).

Здесь есть неплохой справочный пример , в разделе «Потоко-безопасные вызовы элемента управления Windows Forms» .

1
ответ дан 16 December 2019 в 21:38
поделиться

В этом сценарии я подозреваю, что вызов выглядит так:

private void Button1_Click(object sender, ButtonClickEventArgs e)
{
    Control.BeginInvoke(new MethodInvoker(()=> /* code etc. */));
}

Что происходит, так это то, что некоторый код будет выполняться в потоке пула потоков и обновлять элемент управления в потоке, создавшем элемент управления, тогда как если Control .Invoke, какой-то код будет выполняться в потоке, создавшем элемент управления, а также обновлять элемент управления в этом потоке.

1
ответ дан 16 December 2019 в 21:38
поделиться

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

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

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