53

快速提问,我想在启动没有返回值的异步任务之前等待一秒钟。 这是正确的方法吗?

Task.Delay(1000)
    .ContinueWith(t => _mq.Send(message))
    .Start();

异常会发生什么?

4

3 回答 3

52

首先,仅适用于使用构造函数(例如)创建Start()的(非常罕见的) s 。在所有其他情况下,它将抛出异常,因为已经启动或正在等待另一个。TaskTasknew Task(() => _mq.Send(message))TaskTask

现在,可能最好的方法是将代码放入一个单独的async方法中并使用await

async Task SendWithDelay(Message message)
{
    await Task.Delay(1000);
    _mq.Send(message);
}

如果这样做,该Send()方法的任何异常都将在返回的Task.

如果您不想这样做,那么使用ContinueWith()是一种合理的方法。在这种情况下,异常将出现在 from 的Task返回中ContinueWith()

此外,根据 的类型,如果有类似的东西,请_mq考虑使用。SendAsync()

于 2013-10-31T18:33:51.190 回答
13

如果您等待任务完成,您可以捕获任务中引发的任何异常:

请注意,您在 Task 中抛出的异常将是内部异常

class Program
{
    static void Main(string[] args)
    {
        try
        {
            Task task = Task.Delay(1000)
                .ContinueWith(t => Program.throwsException());

            task.Wait();     
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception:" + ex.Message); // Outputs: Exception:One or more errors occurred.
            Console.WriteLine("Inner exception:" + ex.InnerException.Message); // Outputs: Exception:thrown
        }
        Console.ReadKey();

    }
    static void throwsException()
    {
        Console.WriteLine("Method started");
        throw new Exception("thrown");
    }
}
于 2013-10-31T10:25:42.980 回答
0

Wait如果您执行该任务,您将能够观察到任何异常。

由在任务内运行的用户代码引发的未处理异常会传播回加入线程,但本主题后面描述的某些场景除外。当您使用静态或实例 Task.Wait 或 Task.Wait 方法之一时会传播异常,并且您通过将调用包含在 try-catch 语句中来处理它们。

异常处理(任务并行库)的摘录

小心时机。任务使用调度程序,并且不能保证在您说“开始”时开始。您的代码将保证在告诉它之后至少有Start1000 毫秒的延迟,但不能保证完全是 1000 毫秒。

于 2013-10-31T10:23:53.750 回答