2010-02-15 115 views
8

从我对.NET的理解来看,如果我使用BackgroundWorker并为RunWorkerCompleted提供事件处理程序,则该事件处理程序将在调用RunWorkerAsync的同一线程上运行。如果我在代理上使用BeginInvoke来异步运行方法,并将AsyncCallback参数传递给BeginInvoke,那么有没有什么方法可以指定回调在调用BeginInvoke的同一线程上运行 - 或者对于任何线程?根据我的理解,回调将在线程池中的下一个可用线程上运行。这很好,但有没有一种方法可以在我想要的任何线程上的AsyncCallback中运行代码?我知道你可以在窗体或控件上使用BeginInvoke,并在创建UI元素的线程的回调函数中创建代码。但是如果我想在没有窗体或控件的非UI线程上运行代码呢?使用delegate.BeginInvoke时,可以指定运行AsyncCallback的线程吗?

回答

6

在要用作异步操作目标的线程上,CurrentDispatcher属性是一个System.Threading.Dispatcher对象,可用于强制在该线程上执行回调。

这是Control类用来实现BeginInvoke的基类。

有关在Windows窗体中使用此问题的问题。我不认为这会是一个问题,但如果你有一个表单,那么form.BeginInvoke是一个更好的选择。看起来,表单和WPF都使用相同的基类来处理invoke。 http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx

+0

+1的CurrentDispatcher财产... – IAbstract

+0

System.Windows.Threading.Dispatcher是WPF特定的,没有与调用Delegate.BeginInvoke的AsyncCallback的线程有关的任何事情。 –

+1

@Jeff:它提供了一个备用的BeginInvoke方法来允许定位回调。据我所知,这是他真正想要的,只是在提问时混淆了他的术语。 –

0

线程将永远是一个线程池线程,并且永远不会是一个UI线程。

顺便说一句,C#没有BackgroundWorker类。 .NET的确如此。

+0

谢谢。我不是故意暗示BackgroundWorker是C#特有的。我把它拿出来了。 – YWE

0

我做了一个搜索,最后我输入了Jon Skeet's site。有关线程如何与异步委托和回调协同工作的信息非常丰富。我会强烈推荐这个阅读。

5

Delegate.BeginInvoke将始终在ThreadPool中执行委托,并在执行委托的同一个线程上调用AsyncCallback。

你唯一的选择是重新调用您的特定线程回调:

AsyncCallback = delegate (IAsyncResult ar) 
{ 
    wathever.BeginInvoke(delegate 
    { 
     // Do your stuff... 
    }; 
}; 
+0

您的意思是在调用BeginInvoke的同一个线程上调用AsyncCallback?这似乎与我从MSDN文档标题为“异步调用同步方法”(http://msdn.microsoft.com/zh-cn/library/2e08f6yc.aspx)中得知的内容相反,它表示“如果启动异步调用不需要是处理结果的线程,您可以在调用完成时执行回调方法。“ – YWE

+4

不,我的意思是,当您从线程A调用Delegate.BeginInvoke时,此代理将在ThreadPool中的线程B上执行,然后在线程B上调用AsyncCallback。 –

+1

True。我只是验证它。我不认为他们在MSDN文档中说明了这一点。 – YWE

相关问题