【问题标题】:Delay then execute Task延迟然后执行任务
【发布时间】:2013-11-11 07:04:42
【问题描述】:

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

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

异常会发生什么?

【问题讨论】:

  • 为什么要使用异步 CTP?最终版本已经发布了很长时间。如果您可以使用异步方法,则无需手动使用 ContinueWith - 只需等待延迟即可。能否请您提供更多背景信息?
  • @jon: 错误标签 :) 它在 Windows 服务中使用。
  • @JonSkeet 他可能被限制在 .Net 4(为了与 XP 兼容)并且对编译器和目标包感到不舒服。这与我的立场相似。
  • 即使在 .NET 4 中,您也可以使用 BCL Async。 Acync CTP 仅适用于 VS 2010 上的 .NET。顺便说一句,无需调用 Start()Delay 已经开始了任务

标签: c# .net asynchronous task-parallel-library


【解决方案1】:

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

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

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

如果您这样做,Send() 方法的任何异常都将在返回的Task 中结束。

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

另外,根据_mq 的类型,考虑使用SendAsync(),如果有类似的话。

【讨论】:

    【解决方案2】:

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

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

    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");
        }
    }
    

    【讨论】:

      【解决方案3】:

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

      正在运行的用户代码引发的未处理异常 任务内部被传播回加入线程,除了在 本主题后面描述的某些场景。例外 当您使用静态或实例 Task.Wait 或 Task.Wait 方法,您可以通过封装调用来处理它们 在 try-catch 语句中。

      摘自Exception Handling (Task Parallel Library)

      注意时间安排。任务使用调度程序,并且不能保证在您说“开始”时开始。在告诉Start 之后,您的代码将保证至少 1000 毫秒延迟,但不能保证完全正确 1000 毫秒。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-09-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-08
        相关资源
        最近更新 更多