2013-01-23 312 views
0

基於以下問題: General purpose FromEvent method異步/等待+ FromEvent方法

我怎麼知道該事件將返回哪個線程在我的應用程序? 我可以以某種方式指定它會繼續哪個線程? 使用此功能的線程會發生什麼情況?當我使用WPF(Dispatcher/Main/UI線程)時,這些響應看起來很明顯,但如果我正在使用線程MTA,STA,Reactive,ThreadPool(Task/BackgroundWorker),我該如何預測會發生什麼?發生?

是否有比使用task.Wait()(如果我不必擔心鎖定線程)真正的好處?

回答

2

如何知道事件將返回到應用程序中的哪個線程?

你不知道。除非特定事件的文檔指定它將從UI線程,線程池線程等執行,否則你從來不會使用事件。

我能以某種方式指定它會繼續哪個線程?

如果您想在UI線程中運行代碼,然後編組到事件處理程序中的UI線程。如果要在線程池線程中運行代碼,請將新任務添加到處理程序內部的線程池中。如果不需要,這兩項任務都會增加開銷,因此通常最好查看事件的文檔以查看需要哪些內容。

但是,在鏈接問題的情況下,整個想法是,你不再處理事件和事件處理程序,你正在處理一個Task。所以如果你爲任務添加一個延續,問題是這個延續會在哪裏運行?這完全是由你指定的。您可以使用默認的任務計劃程序並讓它在線程池中運行,您可以傳遞一個UI SynchronizationContext以在UI線程中運行,或者您可以讓它在任何正在運行的任務中運行。 (這意味着你不知道將使用什麼線程運行它。)

如果您使用的任務是await,那麼它會自動配置延續,以在您開始執行異步操作前的同步上下文中運行,這可能是也可能不是UI線程(但可能是)。如果您專門請不要想要的,那麼請使用.ConfigureAwait(false);

是否有比使用task.Wait()(如果我不必擔心鎖定線程)真正的好處?

使用基於異步任務的方法的原因是您沒有阻塞線程,特別是線程池線程(因爲您明確表示不會阻塞UI,這會更糟糕)。有一個線程坐在什麼都不做是一個問題,在一些環境比其他更多(如一個高度活躍的網站的ASP)。通過不做阻塞等待,你沒有消耗這些資源。

+1

「,除非特定事件的文檔指定它將從UI線程,線程池線程等執行。」即使這樣*任務延續*可能會運行在不同的線程上。 – usr

+0

@usr在這種情況下,我特指事件而不是任務。我稍後會在答案中找到任務。 – Servy

2

如果你有await a Task,那麼有一個「上下文」被捕獲並用於恢復方法。這個「上下文」是當前的SynchronizationContext,除非它是null,在這種情況下,它是當前的TaskScheduler(這些日子通常是線程池調度器)。

如果你正在做async編程,你應該使用await而不是WaitWait can cause deadlocks, as I explain on my blog

您可能還會發現我的async/await intro有幫助。

1

使用您鏈接到您的技術無法預測它運行的線程。它可能是是提高事件的線索,但這並不是保證(不,實際上!它不是,這是一個常見的錯誤信念)。

因此,您需要強制切換到您想要運行的任何線程。例如,使用Task.Run切換到線程池或使用TaskScheduler.FromCurrentSynchronizationContext在UI上運行。

如果您await您保證在await之前設置的同步上下文中恢復該任務。 這可能是你想要的。