[英]How to cause AggregateException with TPL?
我正在嘗試重新創建將導致此異常的條件:
System.AggregateException: A Task's exception(s) were not observed
either by Waiting on the Task or accessing its Exception property.
As a result, the unobserved exception was rethrown by the finalizer thread.`
我寫這個程序的原因是我會引起異常,但它不會:
using System;
using System.Threading.Tasks;
namespace SomeAsyncStuff
{
class Program
{
static void Main(string[] args)
{
Task.Factory.StartNew(() => { throw new NullReferenceException("ex"); });
GC.Collect();
Console.WriteLine("completed");
}
}
}
在我的實際應用程序中,我使用TPL,但沒有編寫我的異常處理權限。 結果我得到了例外。 現在,我試圖在一個單獨的程序中重新創建相同的條件,以嘗試觀察不到的異常。
您可能需要在GC.Collect()之后添加對GC.WaitForPendingFinalizers()的調用,因為終結器在它們自己的線程上運行。
該異常由TaskExceptionHolder
的終結器拋出,因此終結器線程必須在拋出此異常之前運行。 正如Josh所指出的,您可以通過調用CG.WaitForPedingFinalizers()
來等待。
請注意,此行為已在當前的異步CTP中更改。 我今年早些時候在TechEd Europe上與PFX團隊的Stephen Toub進行了交談,他表示必須更改它才能使新的異步功能正常工作。 因此,盡管現在說下一個框架的下一個版本還為時過早,但是在即將發布的版本中很可能會改變這種行為。
@Sly,盡管您想出了一個有效的答案,但我認為大多數人最好還是聽從錯誤消息建議“ ...等待任務...”。 參與GC活動是您熟悉GC並存在性能瓶頸的信號,或者您錯過了要點。 在我的情況下,這意味着后者;)StartNew調用的確會返回一個Task,那么為什么不使用它呢? 例如
任務myTask = Task.Factory.StartNew(()=> {拋出新的NullReferenceException(“ ex”);}); //給完成任務一些時間
myTask.Wait();
我真的很驚訝您沒有嘗試在任務完成后正確調用代碼,因為誰能說任何進程將在3秒內完成? 不僅如此,而且還占用了其他整個過程3秒鍾的時間。 我將用ContinueWith()任務方法替換該實現,以在任務完成后調用GC。
Task.Factory
.StartNew(() => { throw new NullReferenceException("ex"); })
.ContinueWith(p => GC.Collect());
如果在完成之前需要阻塞(對於用於調試的示例代碼),也可以在啟動任務后執行WaitOne並讓ContinueWith()通知等待處理程序。 如果您必須在生產代碼中執行此操作,那么也許您想要完成的實際上是同步的,而您根本不必擔心使用任務。
我是OP。 我測試了GC.WaitForPendingFinalizers(),但它沒有幫助重新創建異常。 問題在於任務開始之前已執行了GC.Collect()。
這是重新創建異常的正確代碼:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace SomeAsyncStuff
{
class Program
{
static void Main(string[] args)
{
Task.Factory.StartNew(() => { throw new NullReferenceException("ex"); });
// give some time to the task to complete
Thread.Sleep(3000);
GC.Collect();
// GC.WaitForPendingFinalizers();
Console.WriteLine("completed");
}
}
}
重新創建錯誤的最簡單方法是等待任務完成。
Task task = Task.Factory.StartNew(() => { throw new NullReferenceException("ex"); });
//this is where the exception will be thrown
task.Wait();
呼叫等待將阻塞呼叫,直到任務完成執行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.