2010-02-15 116 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

相關問題