我用這樣的代碼:這是異步調用同步方法的正確方法嗎?
handler.Invoke(sender, e);
但隨着代碼的問題是,它是同步的,它確實做到的就是更新GUI。服務器不需要等待它完成,因此它應該是異步的。
我真的不想使用BeginInvoke和EndInvoke,因爲在這種情況下不需要回調方法。
這是一個合適的選擇嗎?
Task.Factory.StartNew(() => handler.Invoke(sender, e));
我用這樣的代碼:這是異步調用同步方法的正確方法嗎?
handler.Invoke(sender, e);
但隨着代碼的問題是,它是同步的,它確實做到的就是更新GUI。服務器不需要等待它完成,因此它應該是異步的。
我真的不想使用BeginInvoke和EndInvoke,因爲在這種情況下不需要回調方法。
這是一個合適的選擇嗎?
Task.Factory.StartNew(() => handler.Invoke(sender, e));
你做的是精細的方式,另一種方式這一點,在.NET 3.5的工作原理是利用ThreadPool
類,而不是
ThreadPool.QueueUserWorkItem(new WaitCallback((a) => handler.Invoke(sender, e)))
此外,如果處理程序恰好是從控制派生,you are allowed to call BeginInvoke without a corresponding EndInvoke.
做我不熟悉C#4的Task類,但我知道BeginInvoke在沒有EndInvoke的情況下工作得很好。我有時會這樣寫代碼:
handler.BeginInvoke(sender, e, null, null);
編輯:我錯了。儘管EndInvoke並不是使代碼在新線程上執行所必需的,但文檔清楚地指出EndInvoke非常重要。
有了這段代碼,'handler'拋出的任何異常都會被忽略。所以如果你想這樣做,你最好知道你在做什麼。 – svick
@Joshua:是的,但是如文檔所述,BeginInvoke調用必須以EndInvoke調用(通常放在回調中)結束。 –
@svick:好點。但是,Task.Factory.StartNew必須具有相同的問題,因爲異常只能在引發它們的線程中捕獲。你必須知道你在做什麼。 –
對GUI的調用很特別,因爲它們必須始終從GUI線程完成。用你自己的話說,handler.Invoke(sender, e)
「更新GUI」,但它可能(不可能)從GUI線程執行,所以它在當前形式中不能正確執行。
在WinForms中,您需要將您的任務代理包裝到Control.Invoke
(或忘記任務並僅使用Control.BeginInvoke
)。
如果是WPF,你可以將你的任務委託包裝成Dispatcher.Invoke
(或者只是在沒有任務的情況下使用Dispatcher.BeginInvoke
)。
我已經在事件處理程序中這樣做了。我想知道如果我也應該異步調用事件處理程序,如果是這樣,如果最初發布的代碼是正確的方式這樣做。 –
'handler'是什麼類型? – svick
@svick:'EventHandler' –
您所想的一切實際上並不奏效。如果你想在UI線程上運行代碼,然後使用Dispatcher.Invoke或Control.BeginInvoke(),無論你選擇的是哪個庫。 –