任务构造函数 vs Task.Run with async Action - 不同的行为 [英] Task constructor vs Task.Run with async Action - different behavior

查看:19
本文介绍了任务构造函数 vs Task.Run with async Action - 不同的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

谁能解释一下这个,也许我遗漏了一些明显的东西.

Could anyone please explain this, perhaps I'm missing something obvious.

这两种情况在行为上似乎相同,但实际上并非如此.

These 2 cases seem to be identical in behavior, and yet they are not.

案例 1:

  • 用一个 async Action, 开始一个任务,它会在一段时间内完成一些工作:

  • Start a Task with an async Action, that does some work for some time:

var t = Task.Run(async () => { await Task.Delay(2000); });

  • 第二个任务等待第一个:

  • A second task waits for the first one:

    var waitingTask = Task.Run(() => { t.Wait(); });
    

  • 等待第二个任务:

  • Wait for the second task:

    waitingTask.Wait();
    

  • 案例 2:

    • 使用 Task 构造函数构建一个 Task,传递相同的 async Action:

    • Build a Task using the Task constructor, passing the same async Action:

    var t = new Task(async () => { await Task.Delay(2000); });
    

  • 开始另一个任务等待第一个(就像第一个例子一样):

  • Start another task to Wait for the first one (just like in the first case):

    var waitingTask = Task.Run(() => { t.Wait(); });
    

  • 开始第一个任务:

  • Start the first task:

    t.Start();
    

  • 等待第二个任务:

  • Wait for the second task:

    waitingTask.Wait();
    

  • 第一个案例表现如预期:等待任务在第一个完成后结束,在 2 秒后.

    The first case behaves as expected: the waiting task ends after the first one does, after 2 seconds.

    第二种情况很奇怪:等待任务结束得很快,比第一种情况早很久.

    打印来自两个任务的消息时很容易看到.第二个任务结束时的打印将显示差异.

    It's easy to see when printing messages from both tasks. A print at the end of the second task will show the difference.

    我正在使用 VS 2015 Preview,如果这很重要,它可能使用 Roslyn 进行编译.

    I'm using VS 2015 Preview, which probably uses Roslyn to compile, if this matters.

    推荐答案

    答案在这里http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx

    实际上,问题是使用 new Task,并且它只能执行 Action,而您正在尝试提供 Func.这里还是前两行,但使用正确的重载重写.

    In effect the issue is that with new Task, and that it can only take a Action, whilst you are trying to give a Func<Task>. Here are the first two lines again, but rewritten using the correct overloads.

    Task t = Task.Run(async () => { await Task.Delay(2000); });
    

    Task<Task> t = new Task<Task>(async () => { await Task.Delay(2000); });
    

    第一个按预期创建任务.第二个创建一个任务,谁的返回类型是一个等待2000ms的任务.由于以下重载,第一个示例有效...

    The first creates a task as expected. The second creates a task, who's return type is a task that waits 2000ms. The first example works because of the following overloads...

     public Task Run(Func<Task>);
     public Task<T> Run(Func<T>);
     public Task<T> Run(Func<Task<T>>);
     etc...
    

    这些重载旨在为您自动调用 Task>.Unwrap().

    These overloads are designed to call Task<Task<T>>.Unwrap() automatically for you.

    结果是在您的第二个示例中,您实际上正在等待第一个任务的开始/入队.

    The result is in your second example you are actually awaiting the start/enqueuing of the first task.

    您可以通过

    var t = new Task<Task>(async () => { await Task.Delay(2000); }).Unwrap();
    

    这篇关于任务构造函数 vs Task.Run with async Action - 不同的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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