2016-05-17 45 views
4

我一直在學習如何使用TPL,並通過article收集了一個示例。我複製並粘貼代碼完全一樣的Task.Run例子,但得到一個錯誤信息,說異常沒有被處理:Try/Catch Wrap Around Task.Run無法處理異常

private async void button1_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     await Task.Run(() => 
     { 
      Thread.Sleep(1000); 
      throw new InvalidOperationException("Hi!"); 
     }); 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.Message); 
    } 
} 

下面是錯誤的圖片:

enter image description here

這個代碼示例是過時的還是我錯過了什麼?

+0

我認爲你需要使用'invoke()',但我不確定 –

+2

如果你不是在調試器中運行這段代碼,我懷疑你會發現消息框顯示 - 你試過了嗎?該異常不是由正在運行任務的線程中的代碼處理的,而是您單獨捕捉到的......我懷疑調試器在這裏有點誤導。 –

+0

@JonSkeet你是對的。當不使用調試器時它工作正常 – Seapoe

回答

4

這只是一個誤導性的調試器消息。

實際發生的事情是拋出異常,然後被.NET框架(而不是用戶代碼)捕獲,然後放置在任務上。

因此,雖然在技術上錯誤消息是正確的(它被.NET框架捕獲 - 未被用戶代碼處理),但在這種情況下它不是很有幫助。

不幸的是,調試器也沒有太多的選擇。在例外離開用戶代碼時,調試器沒有辦法「展望未來」,以知道該例外將被放置在特定的任務上,並且您的代碼將會執行該任務await。它必須立即做出是否通知你的決定,不知道該任務是否爲await ed。

+0

謝謝你的解釋! – Seapoe

-1

您的try/catch運行異步操作,因此不會保存異步操作,因爲當異常被命中時,代碼不保證位於該位置。嘗試在Task.Run(() => {..});內包含try/catch內容

+0

OP正在等待try塊內的任務,所以異常將被傳播並被捕獲。我懷疑「用戶代碼未處理」在這裏有點不準確。 –