我是否正确这个async-await示例没有做任何有用的事情?

时间:2016-12-12 22:36:55

标签: c# .net asynchronous async-await

我正在查看一段代码(我写的是等效的,而不是直接复制粘贴)

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);

没有完成任何事情,因为第二个依赖于第一个的结果。

我对此是否正确?

1 个答案:

答案 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是有用的,而如果,它允许计算机完成的工作超过了其他方式能够完成的工作;在这个特殊的例子中,它没有。