Task.Run和Task.Factory.StartNew之间的不同异常处理 [英] Different exception handling between Task.Run and Task.Factory.StartNew

查看:523
本文介绍了Task.Run和Task.Factory.StartNew之间的不同异常处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用 Task.Factory.StartNew 并尝试捕获异常时遇到了一个问题抛出。在我的应用程序中,我有一个长期运行的任务,我希望将其封装在 Task.Factory.StartNew(..,TaskCreationOptions.LongRunning);

I encountered an issue when I was using Task.Factory.StartNew and tried to capture an exception that is thrown. In my application I have a long running task that I want to encapsulate in a Task.Factory.StartNew(.., TaskCreationOptions.LongRunning);

但是,当我使用 Task.Factory.StartNew 时,没有捕获到异常。但是,当我使用 Task.Run 时,它按预期工作,我认为这只是 Task.Factory.StartNew (例如根据此MSDN文章)。

However, the exception isn't caught when I'm using Task.Factory.StartNew. It is however working as I expect when I use Task.Run, which I thought was just a wrapper on Task.Factory.StartNew (according to for instance this MSDN article).

此处提供了一个工作示例,区别在于使用 Task.Run 时将异常写入控制台,但使用<$时则不c $ c> Factory.StartNew

A working example is provided here, the difference being that the exception is written to console when using Task.Run, but not when using Factory.StartNew.

我的问题是:

如果我有一个 LongRunning 任务,它有可能引发异常,我该如何在调用代码中处理它们?

My question would be:
if I have a LongRunning task that has the possibility to throw exceptions, how should I handle them in the calling code?

private static void Main(string[] args)
{
    Task<bool> t = RunLongTask();
    t.Wait();
    Console.WriteLine(t.Result);
    Console.ReadKey();
}

private async static Task<bool> RunLongTask()
{
    try
    {
        await RunTaskAsync();
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
        return false;
    }
    Console.WriteLine("success");
    return true;
}

private static Task RunTaskAsync()
{
    //return Task.Run(async () =>
    //    {
    //        throw new Exception("my exception");
    //    });
    return Task.Factory.StartNew(
        async () =>
    {
        throw new Exception("my exception");
    });

}


推荐答案

您的问题是 StartNew 不能像 Task.Run async 代表。 StartNew 的返回类型为 Task< Task> (可转换为 Task )。 外部 Task 表示方法的开始,而内部 Task 表示方法的完成(包括任何例外)。

Your problem is that StartNew doesn't work like Task.Run with async delegates. The return type of StartNew is Task<Task> (which is convertible to Task). The "outer" Task represents the beginning of the method, and the "inner" Task represents the completion of the method (including any exceptions).

要进入内部 Task ,可以使用展开。或者,您可以使用 Task.Run 代替 StartNew 进行 async 代码。 LongRunning 只是一个优化提示,实际上是可选的。 斯蒂芬·图布(Stephen Toub)的博客很好地介绍了 StartNew Run 以及为什么 Run 通常(对于)异步代码。

To get to the inner Task, you can use Unwrap. Or you can just use Task.Run instead of StartNew for async code. LongRunning is just an optimization hint and is really optional. Stephen Toub has a good blog post on the difference between StartNew and Run and why Run is (usually) better for async code.

从下面的@usr注释更新: LongRunning 仅适用于 async 方法的开头(直到第一个未完成的操作是 await ed)。因此,在这种情况下,使用 Task.Run 几乎可以肯定更好。

Update from @usr comment below: LongRunning only applies to the beginning of the async method (up until the first incomplete operation is awaited). So it's almost certainly better all around to use Task.Run in this case.

这篇关于Task.Run和Task.Factory.StartNew之间的不同异常处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆