返回Task.Run与Task.Factory.StartNew的类型

时间:2015-01-21 17:23:31

标签: vb.net delegates async-await

我一直在阅读并重新阅读Stephen Cleary的文章StartNew is Dangerous和Stephen Toub的文章Task.Run vs Task.Factory.StartNew。我正试图理解这一点。

给出以下代码:

Dim s = Await Task.Factory.StartNew(New Func(Of Task(Of String))(
    Async Function()
        Await Task.Delay(10000)
        Return "Hello"
    End Function))

Dim t = Await Task.Run(New Func(Of Task(Of String))(
    Async Function()
        Await Task.Delay(10000)
        Return "Hello"
    End Function))

为什么s的类型为Task(Of String)t的类型为String(我期望这样)?

我也可以做以下事情:

Dim u = Await New Func(Of Task(Of String))(
    Async Function()
        Await Task.Delay(10000)
        Return "Hello"
    End Function).Invoke()

其中uString,我可以添加函数:

Async Function GetValueAsync() As Task(Of String)
    Await Task.Delay(10000)
    Return "Hello"
End Function

然后像这样使用它:

Dim v = Await GetValueAsync()

v也是String

那么为什么s不是字符串?

在Stephen Cleary的文章(上面链接)中,他说:

  

[Task.Factory.StartNew]不了解异步委托......问题   当你将异步委托传递给StartNew时,它是很自然的   假设返回的任务代表该委托。但是,自从   StartNew不了解异步委托,实际上是什么任务   代表只是该代表的开始。

我觉得这是整个事情的关键,但我不明白“这个任务实际代表的只是那个代表的开始。” “代表的开始”是什么意思?

1 个答案:

答案 0 :(得分:4)

您可以将Await视为“展开”Task(Of T)到结果类型T

  

为什么s是Task(Of String)类型而t是String类型(我期望)?

Task.Factory.StartNew(New Func(Of Task(Of String))(...)的类型为Task(Of Task(Of String)),因此Await会将其展开到Task(Of String)

Task.Run(New Func(Of Task(Of String))(...)的类型为Task(Of String),因此Await会将其展开到String

  

“代表的开头”是什么意思?

正如我在Async Intro中描述的那样,每个异步方法都开始同步执行,并且只在第一个Await处变为异步。因此,如果您使用的是Task.Factory.StartNew,则会返回Task(Of Task(Of T))。 “外部”任务表示委托的同步执行,直到第一次Await决定屈服于其调用者。此时,Await返回 Task(Of T)给其来电者。此返回的任务是Task(Of Task(Of T))的“内部”任务,它代表该异步委托的完成

但您真正需要知道的唯一事情就是使用Task.Run而不是Task.Factory.StartNew