我遇到了一些使用c#的async
/await
关键字进行异步编程的最佳实践(我是c# 5.0的新手)。
给出的建议之一如下:
稳定性:了解您的同步上下文
...一些同步上下文是不可重入的和单线程的。这意味着在给定时间只能在上下文中执行一个工作单元。这方面的一个例子是Windows UI线程或ASP.NET请求上下文。在这些单线程同步上下文中,很容易死锁。如果您从单线程上下文中生成一个任务,然后在上下文中等待该任务,您的等待代码可能会阻塞后台任务。
public ActionResult ActionAsync()
{
// DEADLOCK: this blocks on the async task
var data = GetDataAsync().Result;
return View(data);
}
private async Task<string> GetDataAsync()
{
// a very simple async method
var result = await MyWebService.GetDataAsync();
return result.ToString();
}
如果我自己尝试剖析它,主线程会在<code>MyWebService中生成一个新线程。GetDataAsync(),但由于主线程在那里等待,因此它在GetDataAsync()中等待结果。result
。同时,说数据准备好了。为什么主线程不继续它的继续逻辑并从<code>GetDataAsync()
有人能解释一下为什么上面的例子有死锁吗?我完全不知道问题是什么...
我只是在ASP中再次处理这个问题。NET是一个MVC项目。当您想从PartialView
调用async
方法时,不允许将PartialView
设置为异步
。如果你这样做,你会得到一个例外。
在要从同步方法调用异步
方法的方案中,可以使用以下简单的解决方法:
SynChronizationContext
同步上下文
示例:
public ActionResult DisplayUserInfo(string userName)
{
// trick to prevent deadlocks of calling async method
// and waiting for on a sync UI thread.
var syncContext = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(null);
// this is the async call, wait for the result (!)
var model = _asyncService.GetUserInfo(Username).Result;
// restore the context
SynchronizationContext.SetSynchronizationContext(syncContext);
return PartialView("_UserInfo", model);
}
返回结果。ToString()
)被排队到UI线程执行僵局可以通过提供替代方案来打破,以避免事实1或事实2。
Stephen Toub的一篇文章很好地解释了这一点,大约在他使用DelayAsync()
示例的一半处。
看看这个例子,斯蒂芬有一个明确的答案给你:
这就是发生的情况,从顶层方法开始(Button1_Click
对于UI/MyController.Get
,对于ASP.NET):
>
顶级方法调用GetJsonAsync
(在UI/ASP.NET上下文中)。
< code>GetJsonAsync通过调用< code>HttpClient来启动REST请求。GetStringAsync(仍在上下文中)。
< code>GetStringAsync返回未完成的< code >任务,表示REST请求未完成。
< code>GetJsonAsync等待< code>GetStringAsync返回的< code>Task。该上下文被捕获,并将在以后用于继续运行< code>GetJsonAsync方法。< code>GetJsonAsync返回未完成的< code >任务,表示< code>GetJsonAsync方法未完成。
顶级方法同步阻塞GetJsonAsync
返回的Task
。这会阻塞上下文线程。
...最终,REST 请求将完成。这样就完成了由字符串异步
返回的任务
。
GetJsonAsync
的延续现在已准备好运行,它等待上下文可用,以便它可以在上下文中执行。
僵局。顶层方法正在阻塞上下文线程,等待< code>GetJsonAsync完成,而< code>GetJsonAsync正在等待上下文释放,以便它可以完成。对于UI示例,“上下文”是UI上下文;对于ASP.NET的例子,“上下文”是ASP.NET请求上下文。这种类型的死锁可能由任一“上下文”引起。
您应该阅读的另一个链接:等待、UI和死锁!天哪!
我试图在react/electron项目中使用async/await,但它不起作用。我想要的是获取docker容器状态列表。但是安慰。日志(列表)返回未定义的。 有人能帮我吗?:)
我在运行以下代码时遇到了一个奇怪的问题: 首先,代码是用OpenJDK-11和OpenJFX-11编译的,在Windows中运行良好(即退出call)。 然而,如果我在Linux(特别是Ubuntu20.04)上运行这个程序,调用会锁定线程,程序永远不会退出。注释出调用将使其重新正常工作。 我只是在(这是SystemLookAndFeel返回的结果)或者我在这里做了什么错误/意外的事情?
我试图使用C++11的std::condition_variable,但是当我试图从第二个线程锁定与其关联的unique_lock时,我得到一个异常“资源死锁已避免”。创建它的线程可以锁定和解锁它,但不能锁定第二个线程,即使我非常肯定unique_lock不应该在第二个线程试图锁定它的地方已经锁定。 FWIW我在Linux中使用gcc4.8.1和-std=gnu++11。 我已经围绕conditi
我有以下代码,这是通过Express调用的API。我需要返回一个引号数组,以及与这些引号相关联的部分数组。为此,我使用async/wait,它在我的引号变量中正常工作,但我在部件变量中得到一个空数组。 我相信这与部分结果是挂起的promise有关,因为当我在循环中记录我的结果时,我得到了适当的值。 我怀疑我一定是误解了async/await是如何工作的,或者promises/Promise是如何工
我正在尝试将数据库调用移出控制器,以清理并使其可测试。当它们在控制器中时,一切都会顺利进行。我将它们移出控制器,并添加了一个异步,以确保我们等待。否则,我将调用的中的函数。现在,一旦我使用async/await,控制器中的函数就会认为没有用户,因为它没有等待。 有几个关于异步等待的SO问题,但我没有找到一个解决我的问题。我确实验证了返回了我的用户,并添加了控制台日志来显示路径。 节点猫鼬异步等待似
我需要在账户之间实现一些基本的资金转移逻辑。为了保持转账的一致性,我利用了同步锁。 这是帐户对象: 这是在transfer worker类中: 我的问题是,如果source Account没有足够的资金,我计划等待该线程,直到它从其他运营中获得资金。对于这个,我一直在等待源帐户。但它以死锁告终,因为目标帐户锁仍在我的帐户上。我怎样才能做到这一点?你能告诉我解决这个问题的正确方法吗? 这就是我试图推