C# BeginInvoke的性能影响
我继承了从主线程(不是后台线程,通常是模式)调用BeginInvoke的代码。我试图理解它在这个场景中的实际作用 在BeginInvoke中调用的方法是否与到达窗口的消息排成一行?文档异步地说C# BeginInvoke的性能影响,c#,visual-studio-2008,.net-2.0,begininvoke,C#,Visual Studio 2008,.net 2.0,Begininvoke,我继承了从主线程(不是后台线程,通常是模式)调用BeginInvoke的代码。我试图理解它在这个场景中的实际作用 在BeginInvoke中调用的方法是否与到达窗口的消息排成一行?文档异步地说,,所以这是我的假设 框架如何确定何时启动BeginInvoke调用的方法的优先级 编辑:代码如下所示: System.Action<bool> finalizeUI = delegate(bool open) { try { // do somewhat tim
,
,所以这是我的假设
框架如何确定何时启动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);
System.Action finalizeEUI=委托(bool打开)
{
尝试
{
//做一些耗时的事情
}
最后
{
Cursor.Current=Cursors.Default;
}
};
Cursor.Current=Cursors.WaitCursor;
BeginInvoke(最终确定,正确);
这在Form_Load事件中发生。在UI线程上调用BeginInvoke的情况下,它仍将经历将Windows消息发布到消息队列的过程,消息将在该队列中等待处理。处理消息时,代理将运行。与从后台线程调用此消息相比,此消息的优先级没有任何不同。edit 现在我们看到了代码,很明显这只是一种将一些初始化从表单加载中移出的方法,但是在用户可以与表单交互之前,它仍然会发生 对
BeginInvoke
的调用在Form\u load中,没有在另一个对象上调用,因此这是对Form.BeginInvoke的调用。现在发生的是这样
我取决于你称之为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的原因之一。在这种情况下,我怀疑调用如下所示:
private void Button1_Click(object sender, ButtonClickEventArgs e)
{
Control.BeginInvoke(new MethodInvoker(()=> /* code etc. */));
}
发生的情况是,一些代码将在线程池线程上运行,并更新创建控件的线程上的控件,而如果使用了control.Invoke,则一些代码将在创建控件的线程上运行,并更新该线程上的控件。在BackgroundWorker广泛使用之前,在对UI线程上创建的控件(即几乎所有控件)执行任何操作之前,必须同步回UI线程
“对Windows窗体控件的线程安全调用”一节中有一个非常好的参考示例。@nobugz,我的措辞很糟糕。我试图说消息本身将位于等待处理的队列上,而不是调用方等待的队列。清除了语言,你确定吗?BeginInvoke是一条PostMessage,而不是SendMessage或SendNotifyMessage?@John,100%确定。SendMessage是同步的,不能与异步BeginInvoke一起工作,因此它使用PostMessage。您可以通过查看reflector中Control.BeginInvoke的实现来查看这一点。实际调用在MarshaledInvoke.JaredPar中:是的,SendMessage不起作用,但是SendNotifyMessage将在发布消息之前传递它,同时仍然不等待消息传递。无论如何,谢谢你的澄清。“我来看看。”约翰,很有趣。我不知道关于SendNotifyMessage的事。我从未使用过API,但我认为Send等同于synchronous,因为它几乎无处不在else@JohnKnoeller,你是说在我的场景中,BeginInvoke承担着线程上下文切换的重量吗?@AngryHacker:不,现在你已经展示了你的代码,很明显这只是JaredPar描述的一条后消息,BeginInvoke是表单上的一个方法,因此不会在单独的线程上运行委托。