2013-07-17 32 views
11

Liệu thử bắt ngoài: await Task.Run(() => có ý nghĩa hoặc chỉ sử dụng chúng chỉ bên trong chờ đợiTry Catch ngoài: đang chờ đợi Task.Run (()

private async void Test() 
{ 
    try 
    { 
     await Task.Run(() => 
     { 
      try 
      { 
        DoingSomething(); 
      } 
      catch (Exception ex) 
      { 
        log.Error(ex.Message); 
      } 
     }); 
     } 
     catch (Exception ex) 
     { 
      log.Error(ex.Message); 
     } 
} 
+1

Điều đó hoàn toàn phụ thuộc vào cách bạn có thể xử lý lỗi. – SLaks

+8

Ngoài ra, không bao giờ viết 'async void'. – SLaks

+0

Tôi có ý định bắt tất cả các lỗi insie od đang chờ đợi nhưng nó an toàn hơn để thêm Try Catch bên ngoài quá? – as74

Trả lời

12

Nếu bạn xử lý Exception bên trong các đại biểu (trong trường hợp của bạn chỉ cần để đăng nhập mục đích), await sẽ không tăng ngoại lệ trong trường hợp bình thường. Điều này sẽ ổn thôi.

private async Task Test() 
{ 
     await Task.Run(() => 
     { 
      try 
      { 
        DoingSomething(); 
      } 
      catch (Exception ex) 
      { 
        log.Error(ex.Message); 
      } 
     }); 

} 

Tuy nhiên, kể từ khi bạn là await ing các Task, có lẽ hầu hết, sẽ có một số DoSomethingElse trong phương pháp Test, mà có thể bị ảnh hưởng bởi kết quả của Task - trong trường hợp này nó cũng làm cho tinh thần để có a try/catch xung quanh await.

private async Task Test() 
{ 
    try 
    { 
     await Task.Run(() => 
     { 
      try 
      { 
        DoingSomething(); 
      } 
      catch (SomeSpecialException spex) 
      { 
        // it is OK to have this exception 
        log.Error(ex.Message); 
      } 
     }); 

     DoSomethingElse(); // does not run when unexpected exception occurs. 
     } 
     catch (Exception ex) 
     { 
      // Here we are also running on captured SynchronizationContext 
      // So, can update UI to show error .... 
     } 
} 
+0

Tôi đã thử điều này trong một ứng dụng giao diện điều khiển, và đặt một break trong bắt, nó không có trong chủ đề chính, tôi ném một lần nữa và không có gì xảy ra. Tôi muốn các chủ đề chính để có được ngoại lệ. tôi có thể làm cái này như thế nào? – pogorman

+0

Ứng dụng @pogorman Console không có SynchronizationContext, vì vậy mã sau khi chờ đợi có thể chạy trên bất kỳ chuỗi nào. Nếu ứng dụng thực tế của bạn là WPF hoặc WinForms, ngoại lệ sẽ được nâng lên trên chủ đề chính – YK1

+0

chiến lược tốt nhất cho ứng dụng bảng điều khiển là gì? Nếu một ngoại lệ xảy ra ở chế độ nền, tôi muốn ứng dụng gặp sự cố nghiêm trọng để các lỗi bị nuốt chửng một cách âm thầm. Cảm ơn. – pogorman

8

Nếu các đại biểu để bạn vượt qua Task.Run đặt ra một ngoại lệ , sau đó bạn có thể bắt nó ngoài Task.Run khi bạn await nhiệm vụ trả lại.

bạn không nên nghĩ đến await như thể nó là một khối. không có những điều như "bên trong chờ đợi". Thay vào đó, suy nghĩ của await với tư cách là nhà điều hành có một đối số duy nhất (trong trường hợp này là Task được trả lại bởi Task.Run). Task.Run sẽ bắt ngoại lệ từ đại biểu của mình và đặt chúng trên Task trả lại; await sau đó sẽ tuyên truyền ngoại lệ đó.

+3

Bạn chỉ có thể bắt ngoại lệ bên ngoài nếu đại biểu được đánh dấu là không đồng bộ ( ngay cả khi không có tuyên bố chờ đợi trong đại biểu) 'đang chờ đợi Task.Run (async() => {throw new Exception ("msg");}); ' – Arvis

+2

@Arvis: Không, bạn có thể bắt nó mà không có' async' bên trong 'Task.Run'. –

+1

Tôi chỉ chạy vào tình huống tương tự này. Tôi không thể bắt được 'SQLException' bên ngoài' Task.Run' trừ khi tôi thêm từ khóa 'async' vào lambda của tôi – NonSecwitter

1

Bạn cũng có thể thêm thử bắt mã ngoài. Trình biên dịch sẽ thực hiện phần bắt khi một ngoại lệ xảy ra trong cuộc gọi async. Dưới đây là chi tiết lý do tại sao bạn sẽ cần cố gắng bắt xung quanh chờ đợi http://msdn.microsoft.com/en-us/library/vstudio/0yd65esw.aspx Exceptions nhìn trong Async Phương pháp