如何通过TPL引起骨料感受?
-
12-10-2019 - |
题
我正在尝试重新创建会导致此例外的条件:
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,并且没有正确处理我的异常处理。结果,我得到了例外。现在,我试图在单独的程序中重新创建相同的条件,以实验未观察到的例外。
解决方案 5
我是OP。我测试了GC.WaitForpending -Fenderizers(),但它无助于重新创建例外。问题是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");
}
}
}
其他提示
您可能需要在GC.Collect()之后向GC.WaitforPending -Fenderizers()添加一个呼叫,因为最终确定器在自己的线程上运行。
例外是由 TaskExceptionHolder
的最终确定器,因此最终测量线程必须在抛出此例外之前运行。正如乔什指出的那样,您可以等待通过打电话来发生这种情况 CG.WaitForPedingFinalizers()
.
请注意,此行为已在当前的异步CTP中更改。我与PFX团队的Stephen Toub谈了今年早些时候在Teched Europe的Stephen Toub,他表示他们必须将其更改为新的异步功能才能正常工作。因此,尽管关于下一个版本的框架还为时过早,但即将在即将推出的版本中很可能会改变这种行为。
@Sly,尽管您想出了一个工作的答案,但我认为大多数人会通过听取错误消息建议“ ...等待任务……”。参与GC活动表明您要么非常了解GC,并且具有性能瓶颈,或者您缺少这一点。就我而言,这意味着后者;)startnew呼叫确实返回任务,所以为什么不使用它呢?例如
任务myTask = task.factory.startnew(()=> {purp turp new nullReferenceException(“ ex”);}); //给完成任务的时间一些
mytask.wait();
我真的很惊讶您没有尝试在完成任务完成后正确调用代码,因为谁说任何过程都将在3秒钟以下完成?不仅如此,这还将其他过程绑定整整3秒。我将用continewith()任务方法替换该实现方法,以在任务完成后调用GC。
Task.Factory
.StartNew(() => { throw new NullReferenceException("ex"); })
.ContinueWith(p => GC.Collect());
如果您需要块直到完成(对于要调试的示例代码),则在启动任务后也可以执行WAITONE,并将ConloceWith()发出信号等待处理程序。如果您必须在生产代码中执行此操作,那么您要完成的工作实际上是同步的,您根本不必担心使用任务。
重新创建错误的最简单方法是等待任务完成。
Task task = Task.Factory.StartNew(() => { throw new NullReferenceException("ex"); });
//this is where the exception will be thrown
task.Wait();
呼叫等待将阻止呼叫,直到任务完成执行为止。