2011-07-04 24 views
37

Tôi có một số mã đơn giản như một repro:chờ vào một nhiệm vụ với một Tiếp tục OnlyOnFaulted gây ra AggregateException

var taskTest = Task.Factory.StartNew(() => 
{ 
    System.Threading.Thread.Sleep(5000); 

}).ContinueWith((Task t) => 
{ 
    Console.WriteLine("ERR"); 
}, TaskContinuationOptions.OnlyOnFaulted); 

try 
{ 
    Task.WaitAll(taskTest); 
} 
catch (AggregateException ex) 
{ 
    foreach (var e in ex.InnerExceptions) 
     Console.WriteLine(e.Message + Environment.NewLine + e.StackTrace); 
} 

Tuy nhiên, tôi nhận được một TaskCanceledException bất ngờ bị ném trong khối try catch (đó là trong Đối tượng ngoại lệ AggregateException). "Một tác vụ đã bị hủy".

Tại sao tôi nhận được ngoại lệ này? Continuation cho công việc không bao giờ cháy, không có ngoại lệ được tạo ra bởi nó, nhưng tôi vẫn nhận được ngoại lệ tổng hợp khi chờ đợi ....

Tôi hy vọng ai đó có thể giải thích cách này có ý nghĩa với tôi :)

+0

tôi đã hoàn toàn kịch bản tương tự như bạn. Tôi nghĩ rằng nó sẽ được thanh lịch hơn và trực quan để chỉ tuyên truyền kết quả của nhiệm vụ trước đó thay thế. Ném một TaskCanceledException là khá đáng ngạc nhiên ... – NickL

Trả lời

53

Bạn không phải đợi công việc với tiếp tục OnlyOnFaulted - bạn đang đợi trên sự tiếp tục đó (được trả về bởi ContinueWith). Việc tiếp tục sẽ không bao giờ cháy vì nhiệm vụ ban đầu trở lại bình thường, vì vậy nó hoạt động như thể nó đã bị hủy bỏ.

Tạo ý nghĩa với tôi.

tôi nghi ngờ bạn muốn tạo ra các nhiệm vụ, thêm việc tiếp tục, nhưng sau đó chờ vào các nhiệm vụ gốc:

var taskTest = Task.Factory.StartNew(() => 
{ 
    System.Threading.Thread.Sleep(5000); 

}); 
taskTest.ContinueWith((Task t) => 
{ 
    Console.WriteLine("ERR"); 
}, TaskContinuationOptions.OnlyOnFaulted); 
+4

Ahh gọi tốt ... Tôi đã suy nghĩ ContinueWith đã trở về nhiệm vụ ban đầu ... – Redth

+0

Giải thích tuyệt vời, chỉ cần một bình luận, trong trường hợp này nó có lẽ tốt hơn không sử dụng Factory.StartNew() phương pháp, bởi vì nhiệm vụ có thể bắt đầu trước khi tiếp tục được xác định. Ở đây tôi sẽ sử dụng hàm Task() mới, sau đó thiết lập phương thức ContinueWith() và cuối cùng gọi phương thức Start(). Nó có ý nghĩa không? –

+1

@JorgeFioranelli: Tại sao nó lại là vấn đề cho nhiệm vụ bắt đầu trước khi việc tiếp tục được xác định? TPL sẽ giải quyết vấn đề này mà không có vấn đề gì. –

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