我正在查看一段代码(我写的是等效的,而不是直接复制粘贴)
public virtual async Task<Something> SomeMethodAsync(string s)
{
string uri = String.Format(stuff, param);
Something something;
HttpResponseMessage responseMsg = await httpClient.GetAsync(uri);
if(responseMsg.IsSuccessStatusCode)
response = await responseMsg.Content.ReadAsAsync<Something>(blah);
else
throw new CreateException(String.Format(problemo));
return response;
}
被称为
public virtual Something GetSomething(string id)
{
return GetOrderAsync(id).Result;
}
我想知道我怀疑这是否有用是正确的。
自方法
public virtual Something GetSomething(string id)
{
return SomeMethodAsync(id).Result;
}
不等待SomeMethodAsync
,这意味着当达到行HttpResponseMessage responseMsg = await httpClient.GetAsync(uri);
并且控制权返回GetSomething
时,在此期间没有可以完成的独立工作。< / p>
此外,有两个等待
HttpResponseMessage responseMsg = await httpClient.GetAsync(uri);
if(responseMsg.IsSuccessStatusCode)
response = await responseMsg.Content.ReadAsAsync<Something>(blah);
没有完成任何事情,因为第二个依赖于第一个的结果。
我对此是否正确?
答案 0 :(得分:3)
它比仅仅无用更糟糕,它是有害的:事实上,以下代码
public virtual Something GetSomething(string id)
{
return SomeMethodAsync(id).Result;
}
将在多个环境(例如Windows窗体)中死锁 - 具体而言,它会在您具有同步上下文的任何环境中死锁。这就是Stephen Cleary et。的原因。 al。强烈建议使用async&#34;一直向下&#34;和not blocking on async code。
以下Windows窗体代码示例死锁,例如:
private async Task<bool> TryThis()
{
Trace.TraceInformation("Starting TryThis");
await Task.Run(() =>
{
Trace.TraceInformation("In TryThis task");
for (int i = 0; i < 100; i++)
{
// This runs successfully - the loop runs to completion
Trace.TraceInformation("For loop " + i);
System.Threading.Thread.Sleep(10);
}
});
// This never happens due to the deadlock
Trace.TraceInformation("About to return");
return true;
}
// Button click event handler
private void button1_Click(object sender, EventArgs e)
{
bool result = TryThis().Result;
// Never actually gets here
Trace.TraceInformation("Done with result");
}
为了解决我对更广泛问题的理解,可以通过以下两种方式之一使用async / await:在单个线程上异步工作或作为在后台线程上工作的更简单方法。通常,您将第一个用于I / O绑定任务(创建线程没有意义只是为了等待结果)而第二个用于CPU绑定任务。
简而言之,这些结构只有在允许程序在相同的时间内完成更多工作时才有用。例如,像:
static void Main(string[] args) {
// This is a terrible thing to do but it's for illustration purposes
Task task = Method1();
task.Wait();
// Some other work
}
private static async Task Method1() {
await Method2();
// Some other work
}
private static async Task Method2() {
await Method3();
// Some other work
}
private static async Task Method3() {
await Task.Delay(1000);
}
然后你基本上只是按顺序运行这些(即使用async并不允许计算机做更多的工作而不是其他方式),所以在这种情况下,#&# 39;小点。
编辑:在非控制台应用中,当然,类似的代码示例可能仍然有用。例如,从注释中,在web服务器中,async / await可以释放线程来完成其他工作。无论哪种方式,重点是async / await是有用的,而仅如果,它允许计算机完成的工作超过了其他方式能够完成的工作;在这个特殊的例子中,它没有。