我一直试图找到一个解决方案很长一段时间,这将告诉我如何创建不使用现有异步代码的异步方法。 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表达式的信息或关于如何解决这个问题的任何其他建议。奇怪的是,我认为我找到了重新锐利的答案给了我过时的建议,我将在下面发布。
答案 0 :(得分:3)
一个强制性的阅读,解释所有这些讨论的根源更好的是微软的“Task-based Asynchronous Pattern”,包括有助于学习“好方法”的例子。从那里抓住以下摘要:
我也是新手,但总结我所学到的是你需要区分IO工作和CPU工作。我从上面的@Stephen Cleary评论中获得了很大的启发。
xxxxAsync()
函数,这是Microsoft的首选机制。如果您的代码包含对外部await xxxxAsync()
,的调用,那么您的功能也可以被视为async
。这样,当CPU空闲等待IO时,调用线程不会被阻塞。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关键字。