问题描述
我想异步执行一些查询.但是当我通过代码进行调试时,大多数时候调用 ToListAsync() 时程序会停止.没有可见的异常,并且调用堆栈窗口被清除.当我在 VS 中按下暂停按钮时,我可以看到调用当前方法之前的堆栈帧.
I want to execute some queries async. But when I debug through the code, most times when an ToListAsync() is called the program stops. There is no visible exception, and the callstack window is cleared. When I press the pause button in VS, I can see the stack frame just before the current method was called.
var res1 = await context.Address().Where(...).ToListAsync();
var res2 = await context.Person().Where(...).ToListAsync();
var res3 = await context.Rule().Where(...).ToListAsync();
有时第一个调用有效,在极少数情况下第二个调用也有效.但至少在第三次调用时程序停止了.我完全不知道为什么......
Sometimes the first call works, in rare cases the second too. But at least at the third call the program stops. I have absolutely no clue why...
推荐答案
来自评论:
这是一个 wpf 应用程序.这些命令在异步方法中.我使用 var result = LoadAsync.Result();
It is a wpf application. The commands are within an async method. I call this from a non-async method using
var result = LoadAsync.Result();
就在那里,这是一个僵局.DispatcherSynchronizationContext
尝试将延续(第一个 await
之后的所有内容)编组回调度程序 (UI) 线程,该线程当前被调用 LoadAsync.Result代码>
Right there, thats a deadlock. The DispatcherSynchronizationContext
tries to marshal the continuation (everything after the first await
) back onto the dispatcher (UI) thread, which is currently blocked by the call to LoadAsync.Result
解决办法:
await
在调用堆栈的顶部,通过使您的方法返回async Task
而不是使用Task.Result
:
await
at the top of your call stack by making your method return anasync Task
instead of usingTask.Result
:
await LoadAsync();
如果您绝对不能将堆栈顶部的方法更改为 async Task
并且由于某些不明原因仍然必须调用 Task.Result
,使用 ConfigureAwait(false)
在等待你的内部异步方法时.这将告诉同步上下文明确不尝试将工作编组回调度程序线程:
If you absolutely cant change the method at the top of of the stack to async Task
and for some obscure reason have to still call Task.Result
, use ConfigureAwait(false)
when awating your inner async methods. This will tell the sync context to explicitly not attempt to marshal work back to the dispatcher thread:
var res1 = await context.Address().Where(...).ToListAsync().ConfigureAwait(false);
var res2 = await context.Person().Where(...).ToListAsync().ConfigureAwait(false);
var res3 = await context.Rule().Where(...).ToListAsync().ConfigureAwait(false);
这篇关于ToListAsync() 根本没有完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!