2013-04-23 11 views
8

Tôi tự hỏi, có ai phải đối mặt với các trường hợp, khi AggregateException.InnerExceptions.Count> 1?Có ai phải đối mặt với các trường hợp, khi AggregateException.InnerExceptions.Count> 1?

Ví dụ: ngoại lệ kết thúc TPL, được nêu trong phần công việc, trong AggregateException. Nhưng tôi chưa bao giờ thấy tình huống, khi có nhiều hơn một ngoại lệ bên trong.

Làm thế nào để đạt được điều này với TPL?
Cách thức này có thể đạt được với bất kỳ lớp học nào FCL (hoặc một thư viện được sử dụng rộng rãi) khác (mẫu sẽ hữu ích)?

Tôi biết, có khả năng để tạo ví dụ như AggregateException, nhưng câu hỏi là về thực tiễn. Tôi hỏi về điều này, bởi vì tôi muốn hiểu, cách tốt nhất để xử lý AggregateException là gì.

+0

Một ví dụ: Nếu bạn có một nhiệm vụ cha mẹ tạo một hoặc nhiều nhiệm vụ con (được đặt thành "đính kèm với cha mẹ"), thì nhiệm vụ của trẻ và nhiệm vụ phụ huynh có thể ném ngoại lệ và trong những trường hợp bạn sẽ kết thúc với hơn ngoại lệ trong AggregateException được trả về từ nhiệm vụ phụ huynh. –

Trả lời

8

Trường hợp điển hình là khi tác vụ phụ thuộc vào nhiều tác vụ và nhiều hơn một trong các tác vụ đó sẽ loại trừ ngoại lệ. Ví dụ:

var t1 = Task.Factory.StartNew(() => { throw new Exception(); }); 
var t2 = Task.Factory.StartNew(() => Console.WriteLine("Innocuous")); 
var t3 = Task.Factory.StartNew(() => { throw new Exception(); }); 

// Output: 2 
var t4 = Task.WhenAll(t1, t2, t3) 
      .ContinueWith(t => Console.WriteLine(t.Exception.InnerExceptions.Count), 
          TaskContinuationOptions.OnlyOnFaulted); 
1

Như Ani đã nói những AggregateExceptions có thể được tạo ra thông qua nhiều kế Task s sử dụng continuations để quan sát các trường hợp ngoại lệ.

Task t1 = Task.Factory.StartNew(() => { throw new Exception(); }); 
Task t2 = Task.Factory.StartNew(() => { throw new Exception(); }); 
Task t3 = Task.WhenAll(t1, t2) 
    .ContinueWith(t => t.Exception.InnerExceptions.Count(), 
    TaskContinuationOptions.OnlyOnFaulted); 

Thông thường bạn sẽ xử lý AggregateException trong khi tiếp tục. Một sự tiếp tục có thể tìm ra nếu một ngoại lệ được ném bởi tiền tố Task bởi tài sản ngoại lệ của nhiệm vụ tiền lệ. Các bản in sau khi kết quả của một NullReferenceException ra cửa sổ Console

Task task1 = Task.Factory.StartNew (() => { throw null; }); 
Task task2 = task1.ContinueWith (ant => Console.Write(ant.Exception()); 

Nếu task1 ném một ngoại lệ và ngoại lệ này không được chụp/truy vấn bằng việc tiếp tục nó được coi là không được quản lý và ứng dụng chết. Với continuations nó là đủ để thiết lập kết quả của nhiệm vụ thông qua các từ khóa Status

asyncTask.ContinueWith(task => 
{ 
    // Check task status. 
    switch (task.Status) 
    { 
     // Handle any exceptions to prevent UnobservedTaskException.    
     case TaskStatus.RanToCompletion: 
      if (asyncTask.Result) 
      { 
       // Do stuff... 
      } 
      break; 
     case TaskStatus.Faulted: 
      if (task.Exception != null) 
       mainForm.progressRightLabelText = task.Exception.Flatten().Message; 
      else 
       mainForm.progressRightLabelText = "Operation failed!"; 
     default: 
      break; 
    } 
} 

đâu ở trên, chúng tôi chỉ mong đợi một ngoại lệ duy nhất - để đảm bảo đây là trường hợp tôi có thể gọi Flatten(). Nếu bạn đang mong đợi các loại ngoại lệ khác, bạn có thể lặp qua các yêu cầu InnerException.

Tôi hy vọng điều này sẽ hữu ích.

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