我继承了从主线程调用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事件中。
答案 0 :(得分:4)
现在我们看到了代码,很明显这只是一种将一些初始化移出Form_Load的方法,但在用户可以与表单交互之前仍然会发生这种情况。
对BeginInvoke
的调用在Form_load中,而不是在另一个对象上调用,因此这是对Form.BeginInvoke的调用。所以发生了什么。
下面的原帖
我依赖于你调用BeginInvoke的对象。如果对象派生自Control
,那么Control.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的一个原因。
答案 1 :(得分:2)
如果在UI线程上调用BeginInvoke,它仍将经历将Windows消息发布到消息将等待处理的消息队列的过程。代理将在处理消息时运行。此消息的优先级不会与从后台线程调用的方式不同。
答案 2 :(得分:1)
在这种情况下,我怀疑这个电话看起来像是:
private void Button1_Click(object sender, ButtonClickEventArgs e)
{
Control.BeginInvoke(new MethodInvoker(()=> /* code etc. */));
}
发生的事情是某些代码将在线程池线程上运行,并更新创建控件的线程上的控件,而如果使用了Control.Invoke,某些代码将在创建控件的线程上运行,并在该线程上更新控件。
答案 3 :(得分:1)
在广泛使用BackgroundWorker之前,您必须在对UI线程上创建的控件执行任何操作之前同步回UI线程(即几乎每个控件)。
在“线程安全调用Windows窗体控件”部分中有一个非常好的参考示例here。