将方法转变为等待

时间:2016-03-22 20:34:04

标签: c# asynchronous async-await

我正在努力巩固我对异步和等待的理解。我终于理解了关于上下文切换的全部内容(这都是魔术)。我写了一个简短的winform程序来玩它。请考虑以下

  private async void button1_Click(object sender, EventArgs e)
      {

        output.Text = "start";
        var intRet = await Task.Run(() => RunALot());
        output.Text += "   after run  ";
        output.Text += intRet.ToString();


    }

    private async Task<int> RunALot ()
    {

        int temp = 0;
        for (int ini = 0; ini <= 40000; ini++)
        {
            temp += ini;
        }
        return temp;
    }
}

我在呼叫Task.Run时已经有RunALot.我是否需要将RunALot的内部包裹到另一个Task.Runawait中那使这真正异步?嵌套上下文有任何性能影响 - 我可以在多大程度上嵌套上下文?

4 个答案:

答案 0 :(得分:5)

RunALot实际上不是异步操作。您已使用async关键字对其进行了标记,但该方法的实现只是同步完成了大量工作,然后在最后返回已完成的Task。您的代码会生成编译器警告,告诉您这一点。

由于RunALot是同步的,因此如果要创建一个Task来表示在另一个线程上异步完成的同步工作。你这样做了。但是,您应该更改它的签名以使其不返回RunALot,而不是让Task谎言并声称是异步的,这样任何人都可以清楚地知道它它实际上并不是异步操作。

答案 1 :(得分:4)

如果某些内容是同步的,并且您只想让UI线程保持空闲,请保持方法签名不含异步任务,并使用Task.Run()包装调用。您不希望您的实现使用Task.Run()强制签署Async,因为它不是异步,它是一种同步方法,您希望UI继续响应而它处理。这个实例中的Task.Run()为您提供了。

直接连接到您的示例,您不需要RunAlot上的异步任务签名,因为它是一个CPU绑定操作,并且本质上不是异步的。

我鼓励您查看以下内容:http://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-dont-use.html

应该是什么的例子:

//tr[td/font[contains(., '202')]]/td

答案 2 :(得分:3)

请记住, async关键字不会使您的代码异步运行。正如Servy已经提到的,RunALot()不是异步方法。如果你想让它异步,你可以这样做:

public static Task<int> RunALot()
{
    return Task.Run(() =>
    {
        int temp = 0;
        for (int ini = 0; ini <= 40000; ini++)
        {
            temp += ini;
        }
        return temp;
    });
}

这就是你可以在button1_Click中调用它的方法:

var intRet = await RunALot();

答案 3 :(得分:2)

您需要在RunALot中创建任务,如下所示。

 private static async Task<int> RunALotAsync()
 {
     // For CPU bound work use Task.Run, Alternate is Task.Factory.StartNew
     return await Task.Run(() =>
     {
         int temp = 0;
         for (int ini = 0; ini <= 40000; ini++)
         {
             temp += ini;
         }
         return temp;
     });
 }

现在等待RunALot调用方法

 var intRet = await RunALotAsync();

Read more关于正确使用async&amp; await