2012-11-07 29 views
5

Tôi về cơ bản tự hỏi làm thế nào tôi nên, trong C#, bắt ngoại lệ từ các phương pháp không đồng bộ được chờ đợi thông qua các từ khóa await. Hãy xem xét ví dụ chương trình điều khiển nhỏ sau đây, quan trọng nhất là chứa một phương thức có tên là AwaitSync. AwaitSync gọi TestAsync, trả về Tác vụ khi được thực hiện ném ngoại lệ. Tôi cố gắng nắm bắt ngoại lệ trong AwaitAsync, nhưng nó không được giải quyết.Làm thế nào để bắt C# ngoại lệ từ một phương pháp không đồng bộ được chờ đợi?

class Program 
{ 
    static void Main(string[] args) 
    { 
     AwaitAsync(); 
     Console.ReadKey(); 
    } 

    static async Task AwaitAsync() 
    { 
     try 
     { 
      await TestAsync(); 
     } 
     catch (Exception) 
     { 
      Console.WriteLine("Exception caught"); 
     } 
    } 

    static Task TestAsync() 
    { 
     return Task.Factory.StartNew(() => { throw new Exception("Test"); }); 
    } 
} 

Làm cách nào để bắt ngoại lệ từ Tác vụ được trả về TestAsync? Trong khi ví dụ này là một chương trình điều khiển, thì vấn đề thực tế của tôi là trong ngữ cảnh của ASP.NET MVC/Web API.

CHỈNH SỬA: Tắt ngoại lệ bị bắt vì lý do kỹ thuật Tôi không nhận thấy thông báo 'Ngoại lệ bị bắt' trước khi trạm đóng. Trong mọi trường hợp, câu trả lời của Jon Skeet rất có giá trị với sự hiểu biết của tôi về await và xử lý ngoại lệ.

+1

Bạn có nói rằng điều này không hoạt động? – jishi

+2

Khi tôi chạy mã của bạn, tôi thấy "Ngoại lệ bị bắt". – spender

+0

Nó không bị bắt cho tôi. Tôi sẽ kiểm tra lại. – aknuds1

Trả lời

10

Các mã được tạo cho các biểu hiện await sẽ gọi GetResult() trên TaskAwaiter gắn liền với Task trả về bởi TestAsync.

GetResult sẽ nhận thấy rằng nhiệm vụ được faulted, lấy ngoại lệ đầu tiên từ AggregateException trong công việc, và vứt đó. Kết quả là khối catch của bạn sẽ bắt được ngoại lệ trong nhiệm vụ của bạn - nhưng nếu bạn chờ đợi một nhiệm vụ có nhiều trường hợp ngoại lệ, bạn sẽ chỉ thấy trường hợp đầu tiên trừ khi bạn thực hiện các hành động đặc biệt (có phương pháp tiếp cận khác nhau này).

Vì bạn đang tuyên bố ngoại lệ thực sự không được giải quyết, có vẻ như có gì đó trong mã của bạn khác với những gì bạn đang hiển thị - vì mã bạn đã cung cấp chắc chắn sẽ hoạt động và cho tôi.

+0

Xin cảm ơn, sẽ xây dựng sau bữa trưa. – aknuds1

+0

Thực ra, ngoại lệ là thực tế bị bắt, nhưng thông báo xác nhận không được viết ra bàn điều khiển trước khi tôi nhấn một phím để kết thúc chương trình. Vì vậy, tôi đã không nhận thấy thông báo được in lúc đầu. Đoán không đồng bộ mất một số nhận được sử dụng để :) – aknuds1

+0

Cảm ơn rất nhiều btw cho lời giải thích của bạn về cách xử lý ngoại lệ với chờ đợi, rất hữu ích cho sự hiểu biết của tôi. – aknuds1

Các vấn đề liên quan