如何使用async和await创建自己的异步方法

时间:2014-02-22 13:12:15

标签: c# async-await

我一直试图找到一个解决方案很长一段时间,这将告诉我如何创建不使用现有异步代码的异步方法。 IE someClass.ActionAsync() 我基本上一直想做像

这样的事情
public string GetParsedData(string code){
    Console.WriteLine("Starting parser");
    var result = "";
    foreach(var x in code.Split('\n')){
          result += Encode(x);
    }

    return result;

}

所以我理解我必须返回一个Task,但是我没有找到关于如何等待lambda表达式的信息或关于如何解决这个问题的任何其他建议。奇怪的是,我认为我找到了重新锐利的答案给了我过时的建议,我将在下面发布。

2 个答案:

答案 0 :(得分:3)

一个强制性的阅读,解释所有这些讨论的根源更好的是微软的“Task-based Asynchronous Pattern”,包括有助于学习“好​​方法”的例子。从那里抓住以下摘要:

我也是新手,但总结我所学到的是你需要区分IO工作和CPU工作。我从上面的@Stephen Cleary评论中获得了很大的启发。

  • 对于 IO绑定密集型工作,您已经拥有.NET中可用的外部xxxxAsync()函数,这是Microsoft的首选机制。如果您的代码包含对外部await xxxxAsync()的调用,那么您的功能也可以被视为async 。这样,当CPU空闲等待IO时,调用线程不会被阻塞。
  • 对于 CPU绑定密集型工作,没有任何外部可用的xxxxAsync()函数可以调用,.NET中有一个现有的包装器可以调用您的代码:Task.Factory.StartNew(NET-4.0)或者更简单,更好Task.Run(NET-4.5),后者在这种情况下是微软的首选(*)。如果您的代码包含对await Task的调用或返回Task,那么您的功能也可以被视为async 。这样,当密集型任务在ThreadPool中运行时,调用线程不会被阻止。

(*)此机制不被认为是为CPU密集型函数创建异步包装器。如果你正在创建一个库,特别是永远不要这样做。相反,它反过来说:你应该使用Task.Run从代码中调用现有的 sync CPU密集型函数

现在,我发现由CPU密集型操作阻止的WEB-UI线程的最佳示例here。你可以直接去那里跳过理论部分。

答案 1 :(得分:0)

所以Resharper建议我使用TaskEx.Run(不推荐使用),正确答案似乎是Task.Run。我发现成功重写了这个方法,

public async Task<string> GetParsedData(string code){
    Console.WriteLine("Starting parser");
    var taskResult = await Task.Run(() =>
    {
        var result = "";
        foreach(var x in code.Split('\n'))
        {
            result += Encode(x);
        }

        return result;
    });
    return taskResult;
}

现在我可以根据需要在其他异步方法中使用此方法的await关键字。