我正在尝试重新创建会导致此例外的条件:

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();

呼叫等待将阻止呼叫,直到任务完成执行为止。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top