我一直在阅读并重新阅读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()
其中u
是String
,我可以添加函数:
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不了解异步委托,实际上是什么任务 代表只是该代表的开始。
我觉得这是整个事情的关键,但我不明白“这个任务实际代表的只是那个代表的开始。” “代表的开始”是什么意思?
答案 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
。