我有以下程序似乎很简单,但只是在没有超时的情况下连续等待:
Public Overrides Async Function ExecuteReaderAsync() As Task(Of Boolean)
If Not IsNothing(Command) Then 'Command is a the standard SqlCommand object
If Not IsNothing(Command.Connection) Then
Try
ExecutionFailed = True
Command.Connection.Open()
Reader = Await Command.ExecuteReaderAsync
IsExecuted = True
ExecutionFailed = False
Return True
Catch ex As Exception
Debugger.Break()
End Try
End If
End If
Return False
End Function
上面的代码执行Reader = Await Command.ExecuteReaderAsync行并挂起。
如果我用这些替换该行:
Dim t = Command.ExecuteReaderAsync
Reader = Await t
并在等待中断,我可以看到任务t的状态为WaitingForActivation。我还可以在SQL事件探查器上看到读者正在调用的SP已正确执行。
现在对于奇怪的部分 - 如果我添加一个thread.sleep 10ms,然后看看t,该任务将RunToCompletion作为其状态,并且一切都在世界上。
Dim t = Command.ExecuteReaderAsync
System.Threading.Thread.Sleep(10)
Reader = Await t
我非常愿意接受我做错了什么(通常是这种情况......)但我不知道在这种情况下是什么。
答案 0 :(得分:4)
答案是与上下文有关,我的代码导致死锁。这个页面对我非常有帮助,并提供了有关死锁发生原因的完整解释:
Don't Block on Async Code - Stephen Cleary
解决方案是以下列方式将ConfigureAwait应用于任务:
Await Command.Connection.OpenAsync.ConfigureAwait(False)
Reader = Await Command.ExecuteReaderAsync.ConfigureAwait(False)
我正在从MySql迁移到SQL Server - MySql async命令似乎没有出现同样的问题而且不需要ConfigureAwait。