2015-09-27 84 views
1

問題的確切含義如下。有沒有保證AsyncCallbacks總是在主線程上執行?

我已閱讀MSDN文章here,並且(除非我是盲人),無法在任何地方看到它明確證實這一點。

爲了給出更多的範圍,我主要參考Socket類中提供的Socket.Beginxxx方法。

我認爲任何AsyncCallbacks將在主線程中執行是否安全?假設我調用的任何Socket.Beginxxx方法也將從主線程調用。

編輯︰如果不是這樣的話,我應該lock包含類的私人成員,當我修改它們中的一個Socket.Beginxxx AsyncCallbacks?例如。將一個項目添加到字典?

+0

不是。做出這個一攬子假設並不安全。當然,在UI線程中,當處理ASP.net應用程序中的請求時,你的延續將被整理回原始上下文,但是在控制檯應用程序(可能還有其他幾個我沒有想到的環境)中,沒有這樣的保證。 – spender

+0

這是因爲爲什麼? –

+0

閱讀:http://blogs.msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx – spender

回答

4

我讀過這裏給出的MSDN文章,並且(除非我是盲人)看不到任何明確證實這一點的地方。

相關引號(強調):

使用一個AsyncCallback委託處理異步操作的結果在單獨的線程

回調是而不是保證在原始線程中執行;實際上,它保證在的另一個線程(即線程池線程)上運行。

儘管有其他答案,但這與SynchronizationContext完全無關,或者TAPEAP如何與其上下文配合使用。 AsyncCallbackAPM的一部分 - 最古老的異步模式 - 它絕對不會爲您自動執行線程編組。

如果情況並非如此,當我在其中一個Socket.Beginxxx AsyncCallbacks中修改它們時,是否應該鎖定包含類的私有成員?例如。將一個項目添加到字典?

你可以。我在我的異步套接字代碼中發現,將所有回調封裝回負責所有套接字操作和相關數據的單個共享線程會更容易。然後不需要鎖定,因爲所有「已完成的事件」都被同步到一個單獨的線程。

+0

我根本沒有注意到這一點,我的錯誤。你認爲使用你的方法比使用鎖更有效嗎?如果是這樣,有沒有機會舉例說明你是如何做到這一點的?線程不是我的強項。 –

+0

@LukePark:如果可能的話,我建議使用SignalR而不是原始套接字。但是如果你使用原始套接字,你可以使用'SynchronizationContext.Post'來通知套接字事件的主線程,或者使用我的'ClientTcpSocket'類[這個有點過時的庫](https://nitoasync.codeplex.com/ )。 –

0

不可以。你的假設並不總是成立。有些框架可能會覆蓋重寫同步上下文以在特定線程上調用延續,但在語言級別上無法保證。下面是斯蒂芬Toub說,它(在very informative post關於這個問題):

框架可以從獲得的SynchronizationContext自己的背景和覆蓋Post方法更適合於調度所代表。例如,在Windows窗體的情況下,WindowsFormsSynchronizationContext實現Post以將代理傳遞給Control.BeginInvoke。對於WPF中的DispatcherSynchronizationContext,它調用Dispatcher.BeginInvoke。等等....那怎麼等待「帶你回到原來的位置。」

隨着不變SychronizationContext(如用一個控制檯應用程序),則延續將排隊到線程池,等有效地,它可以在任何線程上運行。

相關問題