.net 为什么等待的代码会无限期冻结?
我有以下代码:.net 为什么等待的代码会无限期冻结?,.net,vb.net,asynchronous,async-await,.net,Vb.net,Asynchronous,Async Await,我有以下代码: Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim t = DoStuffAsync() t.Wait() Debug.Print(t.Result) End Sub Private Async Function DoStuffAsync() As Task(Of String) Await Task.Delay(2000)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim t = DoStuffAsync()
t.Wait()
Debug.Print(t.Result)
End Sub
Private Async Function DoStuffAsync() As Task(Of String)
Await Task.Delay(2000)
Return "Stuff"
End Function
我知道这不是正确的方法。以下是我认为可能是正确的方法:
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim t = DoStuffAsync()
Debug.Print(Await t)
End Sub
Private Async Function DoStuffAsync() As Task(Of String)
Await Task.Delay(2000)
Return "Stuff"
End Function
不过,我只是想知道,当我运行第一个代码示例时,为什么它无限期地挂在
t.Wait()
上?此时代码执行的具体情况是什么,即当线程在t.Wait()上被阻塞时,什么代码正在“运行” 这是死锁。您正在UI线程上运行Task.Delay
。然后阻止UI线程等待任务。延迟完成。你是对的:你应该等待任务
死锁。您正在UI线程上运行Task.Delay
。然后阻止UI线程等待任务。延迟完成。你是对的:你应该等待完成任务
让我们先解决实际问题:是的,你应该等待而不是等待结果。现在谈谈你为什么会发生这种情况的问题
在本书中,他解释了这是如何发生的。以下是他的“发生了什么”演练,根据您的方法进行了修改:
顶级方法按钮1\u单击调用dostufasync
(在UI上下文中)
DoStuffAsync
调用Task.Delay
(仍在上下文中)
Task.Delay
返回未完成的任务,表示时间尚未过去
dostufasync
等待Task.Delay
返回的Task
。将捕获上下文,并将用于以后继续运行DoStuffAsync
方法dostufasync
返回未完成的任务
,表示dostufasync
方法未完成
顶级方法同步阻止由DoStuffAsync
返回的任务。这将阻止上下文线程
…最终,指定的时间将过去,延迟
任务将完成
DoStuffAsync
的继续现在可以运行了,它等待上下文可用,以便可以在上下文中执行
僵局。顶级方法正在阻止上下文线程,等待dostufasync
完成,而dostufasync
正在等待上下文释放以便完成
在这个UI上下文中,这也恰好是一个特定的线程,但不需要强制转换。例如,在ASP.NET中,有一个上下文可以在任何线程上运行,但一次只能在一个线程上运行。重要的是上下文被锁定,不管它实际运行在什么线程上。让我们先解决实际问题:是的,您应该等待结果,而不是等待结果。现在谈谈你为什么会发生这种情况的问题
在本书中,他解释了这是如何发生的。以下是他的“发生了什么”演练,根据您的方法进行了修改:
顶级方法按钮1\u单击调用dostufasync
(在UI上下文中)
DoStuffAsync
调用Task.Delay
(仍在上下文中)
Task.Delay
返回未完成的任务,表示时间尚未过去
dostufasync
等待Task.Delay
返回的Task
。将捕获上下文,并将用于以后继续运行DoStuffAsync
方法dostufasync
返回未完成的任务
,表示dostufasync
方法未完成
顶级方法同步阻止由DoStuffAsync
返回的任务。这将阻止上下文线程
…最终,指定的时间将过去,延迟
任务将完成
DoStuffAsync
的继续现在可以运行了,它等待上下文可用,以便可以在上下文中执行
僵局。顶级方法正在阻止上下文线程,等待dostufasync
完成,而dostufasync
正在等待上下文释放以便完成
在这个UI上下文中,这也恰好是一个特定的线程,但不需要强制转换。例如,在ASP.NET中,有一个上下文可以在任何线程上运行,但一次只能在一个线程上运行。重要的是,上下文是锁定的,不管它实际运行在什么线程上。好的,所以我在阅读时开始感到困惑。看起来OP的示例代码在“我可以这样重写它:”下面会遇到与我的问题相同的情况,但是Eric Lippert在他的回答中说,“现在,如果你确实需要出于某种原因跟踪任务,那么你描述的技术是完全合理的。”我哪里搞混了?是Wait
方法导致了问题。你刚才读的问题是关于async void
方法的用例,并且没有调用Wait
。好吧,所以我开始在阅读时感到困惑。看起来OP的示例代码在“我可以这样重写它:”下面会遇到与我的问题相同的情况,但是Eric Lippert在他的回答中说,“现在,如果你确实需要出于某种原因跟踪任务,那么你描述的技术是完全合理的。”我哪里搞混了?是Wait
方法导致了问题。您阅读的问题是关于async void
方法的用例,并且没有调用Wait
。可能重复的可能重复感谢这一点,它提供了非常丰富的信息。最近我读了很多斯蒂芬·克利里的书,但我还没有读到这本书。谢谢你,这本书内容丰富。我已经读过了