6

我继承了从主线程(不是后台线程,通常是模式)调用 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 事件中。

4

4 回答 4

4

编辑

现在我们看到了代码,很明显这只是一种将一些初始化移出 Form_Load 的方法,但仍然在用户与表单交互之前发生。

调用BeginInvoke在 Form_load 内部,而不是在另一个对象上调用,因此这是对 Form.BeginInvoke 的调用。所以发生的事情是这样的。

  1. Form_Load 将委托传递给 Form.BeginInvoke,这会将消息放入表单的消息队列中,该队列位于所有用户输入消息之前。它将光标设置为等待光标。
  2. Form_Load 返回,并允许表单初始化的其余部分完成,此时表单很可能变得可见。
  3. 一旦代码进入消息泵,首先在队列中看到的是委托,所以它运行它。
  4. 当委托完成时,它将光标改回正常光标,并返回
  5. 利润!

下面是原帖


我取决于您调用 BeginInvoke 的对象。如果对象派生自,ControlControl.BeginInvoke将在创建控件的线程上运行。请参阅 JaredPar 的回答。

但是还有另一种使用 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 的原因之一。

于 2010-03-18T21:21:34.677 回答
2

在 UI 线程上调用 BeginInvoke 的情况下,它仍会经历将 Windows 消息发布到消息队列的过程,消息将在该队列中等待处理。处理消息时,委托将运行。此消息的优先级与从后台线程调用的方式不同。

于 2010-03-18T20:58:37.797 回答
1

在这种情况下,我怀疑电话看起来像:

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

发生的事情是一些代码将在线程池线程上运行,并更新创建控件的线程上的控件,而如果使用 Control.Invoke,则一些代码将在创建控件的线程上运行,并更新控件那个线程也是如此。

于 2010-03-18T21:25:48.193 回答
1

在广泛使用 BackgroundWorker 之前,您必须在对 UI 线程上创建的控件(即几乎每个控件)执行任何操作之前同步回 UI 线程。

“对 Windows 窗体控件的线程安全调用”部分中有一个很好的参考示例。

于 2010-03-18T21:56:46.653 回答