繁体   English   中英

处理UnobservedTaskException

[英]Handling UnobservedTaskException

我有一个配置为捕获在app.config中启用ThrowUnobservedTaskExceptions =“ =” true“的任何未观察到的任务异常的应用程序。

我有一个需要在其构造函数中启动异步任务的库类(Class1),但是在某些情况下会引发异常,并且在处理Class1实例时会遇到UnobservedTaskException错误(因为从未等待该任务)。

我通过在构造函数中的任务上附加一个ContinueWith并通过将TaskContinuationOptions设置为OnlyOnFaulted来处理异常(通过访问任务的Exception属性)来解决此问题,并且效果很好。

现在我遇到的问题是,这个异步任务(我在构造函数中初始化)也正在类的方法中等待验证验证,以确保在继续执行方法中的其余代码之前已完成任务。 如果我在实例化我的class(Class1)之后调用了此方法,并且抛出了错误,则执行我附加的ContinueWith并处理异常。 我不要这种行为。 如果在方法内部等待时导致错误,我希望它引发异常。

我只希望unobservedtaskexceptions只在这种情况下处理(而不是在整个应用程序中处理)-这是在Class1初始化且没有调用任何方法的情况下,如果任务引发异常,则在ContinueWith中处理它。 我不希望在方法内部等待此任务时(如果抛出)执行ContinueWith中的代码。

这是将提供更多清晰度的代码。 请让我知道我是否有办法实现这一目标。

Program.cs

using (Class1 c = new Class1())
{
       c.ValidateInitializeAsync().Wait(); // I want this to throw. Only if this line is commented, I want the exception to be handled.
}

// The application needs to be run in Release mode in order for GC to dispose c and enter into the scenario I want
while (true)
{
    Thread.Sleep(100);
    GC.Collect();
    GC.WaitForPendingFinalizers();
 }

Class1.cs

class Class1 : IDisposable
{
    public Task initializeTask;

    public Class1()
    {

        this.initializeTask = TaskHelper.InlineIfPossible(() => RunTask()).ContinueWith(t =>
        {
            Console.WriteLine(string.Format("Exception handled, {0}", t.Exception.HResult));

        }, TaskContinuationOptions.OnlyOnFaulted);
    }

    public async Task ValidateInitializeAsync()
    {
        await this.initializeTask;
    }
    public async Task RunTask()
    {
        await Task.Run(() =>
        {
            Console.WriteLine("Running task...");
            Task.Delay(5000).Wait();
            throw new InvalidOperationException("exception occured");
        });
    }

    public void Dispose()
    {
        Console.WriteLine("Class1 disposed.");
    }
}

static class TaskHelper
{
    static public Task InlineIfPossible(Func<Task> function)
    {
        if (SynchronizationContext.Current == null)
        {
            return function();
        }
        else
        {
            return Task.Run(function);
        }
    }
}

您要的是不可能的。 随着时间的流逝,想一想:当RunTask出现异常时,代码必须正确知道然后是否处理该异常。 它无法展望未来并确定是否将由 await堆栈的进一步处理。

我建议使用异步工厂模式 ,以便在调用代码获取实例之前立即传播所有初始化异常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM