我在看一段代码是这样的(我写的是等价的,不是直接复制粘贴的)
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
,在此期间没有独立的工作可以完成。
此外,还有两个等待
HttpResponseMessage responseMsg = await httpClient.GetAsync(uri);
if(responseMsg.IsSuccessStatusCode)
response = await responseMsg.Content.ReadAsAsync<Something>(blah);
没有完成任何事情,因为第二个取决于第一个的结果。
我说得对吗?
最佳答案
它比无用更糟糕,它是积极有害的:事实上,下面的代码
public virtual Something GetSomething(string id)
{
return SomeMethodAsync(id).Result;
}
会在多种环境(例如 Windows 窗体)中死锁 - 具体来说,它会在任何具有同步上下文的环境中死锁。这就是 Stephen Cleary 等人的原因。 al. 强烈建议“一直向下”使用异步和 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 绑定(bind)任务(创建线程只是为了等待结果是没有意义的),第二个用于 CPU 绑定(bind)任务。
简而言之,这些结构只有在允许程序在相同的时间内完成比其他情况下更多的工作时才有用。例如,像这样的东西:
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);
}
那么您基本上只是按顺序运行这些(即使用异步不允许计算机做比其他方式更多的工作),所以在这种情况下没有什么意义。
编辑:当然,在非控制台应用程序中,类似的代码示例可能仍然有用。例如,根据评论,在 Web 服务器中,async/await 可以释放线程来做其他工作。无论哪种方式,关键是 async/await 是有用的,如果,仅,它允许计算机完成比它本来能够完成的更多的事情;在这个特定示例中,它没有。
关于c# - 我是否正确认为这个 async-await 示例没有做任何有用的事情?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41110863/