调用异步方法和在async/await中使用TaskScheduler

4
考虑以下代码:
async Task<int> foo()
{
    await Task.Delay(1000);
    return 42; 
}

...
// OPTION 1

Task t = Task.Factory.StartNew(foo,
            CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);

t.Wait();


...
// OPTION 2
Task t = foo();
t.Wait()

以下是需要翻译的内容:

  1. 两种调用选项有什么实质性区别?

  2. 对于选项1,如果我重写默认的TaskScheduler,在foo方法中使用await,将使用哪个TaskScheduler?会使用默认的还是传递给父任务的参数?


1
选项2甚至不会启动线程? - H H
1
@Henk 它开始并执行。 - Boris
@Henk 我相信至少 Task.Delay 部分将在线程池线程上执行。 - Boris
1
Delay()不需要占用线程。 - H H
1个回答

3
一般来说,“选项1”将创建一个新的任务,用于包装对foo()的调用,实际上会创建一个Task<Task<int>>。当您在其上调用.Wait()时,它不会等待内部任务完成,因为内部任务会立即返回(一旦达到Task.Delay)。
至于您关于使用非默认TaskScheduler的问题,一般情况下,它不会改变行为,除了它可能会阻塞,直到自定义调度程序启动任务。如果没有关于所讨论的调度程序的更多信息,就无法确定会发生什么。
然而,第二个选项将阻塞,直到延迟完成,因为它将启动任务,并阻塞直到延迟完成后才继续执行。

@Boris 不会,但Task.Factory.StartNew将使用您的调度程序,该调度程序实际上可能或可能不会启动该任务 :) - Reed Copsey
这是解释它的链接 - http://blogs.msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx - Boris
@Boris 你无法为 await 调用内部的任务指定调度程序... 没有这样的机制。你只能使用 TaskFactory 调度“顶层”的任务。 - Reed Copsey
有点令人失望。我本以为如果可以重写SynchronizationContext,那么也应该能够重写TaskScheduler...无论如何,非常感谢您的回答。 - Boris
1
@Boris,这可能是一个不同的线程,但一次只能有一个... - Reed Copsey
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接