在没有等待 #2 的情况下调用异步方法
Posted
技术标签:
【中文标题】在没有等待 #2 的情况下调用异步方法【英文标题】:call async method without await #2 【发布时间】:2013-11-16 04:14:17 【问题描述】:我有一个异步方法:
public async Task<bool> ValidateRequestAsync(string userName, string password)
using (HttpClient client = new HttpClient())
HttpResponseMessage response = await client.GetAsync(url);
string stringResponse = await response.Content.ReadAsStringAsync();
return bool.Parse(stringResponse);
我这样称呼这个方法:
bool isValid = await ValidateRequestAsync("user1", "pass1");
我可以从同步方法中调用相同的方法,而不使用await
关键字吗?
例如:
public bool ValidateRequest(string userName, string password)
return ValidateRequestAsync(userName, password).Result;
我认为这会导致死锁。
编辑
调用上述方法会使调用永远不会结束。 (方法不再结束)
【问题讨论】:
我相信在没有 await 的情况下调用异步方法只会导致该方法被同步调用,结果行为将取决于您的方法实际执行的操作。 我试过了!看起来方法调用永远不会结束 @Chris 该方法总是被同步调用。它只是返回一个任务,这是唯一的区别。所有的魔法都在等待中,而不是在通话中。 啊,我明白了,我还没有真正使用过异步;我需要去阅读更多关于机制的信息。谢谢。 您的方法可能会死锁,但这是您的逻辑的结果,而不是您以同步方式调用它的事实。 【参考方案1】:如果从单线程执行上下文(如 UI 线程)调用异步方法,并同步等待结果,则很有可能发生死锁。在您的示例中,该概率为 100%
考虑一下。当你打电话时会发生什么
ValidateRequestAsync(userName, password).Result
您调用方法 ValidateRequestAsync。在那里你调用 ReadAsStringAsync。结果是一个任务将返回给 UI 线程,并计划在它可用时继续在 UI 线程上执行的延续。但当然,它永远不会变得可用,因为它正在等待(阻塞)任务完成。但任务无法完成,因为它正在等待 UI 线程变得可用。死锁。
有一些方法可以防止这种僵局,但它们都是一个坏主意。为了完整起见,以下方法可能有效:
Task.Run(async () => await ValidateRequestAsync(userName, password)).Result;
这是个坏主意,因为你仍然会阻塞你的 UI 线程等待并且没有做任何有用的事情。
那么解决办法是什么?一路异步。 UI 线程上的原始调用者可能是某个事件处理程序,因此请确保它是异步的。
【讨论】:
知道了。解决方案是创建一个 Sync 和一个 Async 方法? 某些 asp.net web api 操作过滤器不支持异步方法 @RaraituL 这是真的,.ConfigureAwait
可能会帮助你。但要小心:动作过滤器应该运行得很快。使用.Result
会阻塞线程,这是应该避免的,在动作过滤器中也是如此。
不,task.ConfigureAwait(false).Result
肯定行不通。它甚至不会编译,因为 ConfigureAwait()
不会返回 Task
。
就我而言,我不在乎它是否阻塞了主线程——它是每周手动启动一次的进程——很好的答案【参考方案2】:
你可以使用return ValidateRequestAsync(userName, password).GetAwaiter().GetResult();
【讨论】:
哦,这真的很好看,值得更多的支持。 这似乎不起作用。进程挂起,就像您执行 ValidateRequestAsync(userName, password).Result 一样。 Kris 回应的“坏主意”起到了作用:Task.Run(async () => await ValidateRequestAsync(userName, password)).Result【参考方案3】:对我来说,它在异步调用中使用 .ConfigureAwait(false) 设置。我有类似的东西
return await Entities.SingleOrDefaultAsync(.....).ConfigureAwait(false);
【讨论】:
以上是关于在没有等待 #2 的情况下调用异步方法的主要内容,如果未能解决你的问题,请参考以下文章