2014-02-11 231 views
4

在文档浏览:http://msdn.microsoft.com/en-us/library/hh191443.aspx表明:C#异步无需等待

如果异步方法不使用的await操作,以纪念悬挂 点,方法,执行的同步方法确实,尽管 异步修改器。编译器为这些方法发出警告。

我相信这是警告:

这种异步方法缺乏“等待”运营商和将同步运行。 考虑使用'await'操作符来等待非阻塞API调用 或'await Task.Run(...)'在后台线程上执行CPU绑定工作。

然后,在一个不同的,引用链路,http://msdn.microsoft.com/en-us/library/windows/apps/hh994635.aspx,它显示的例子如下:

public class Example 
{ 
    // ... 
    private async void NextMove_Click(object sender, RoutedEventArgs e) 
    { 
     await Task.Run(() => ComputeNextMove()); 
     // Update the UI with results 
    } 

    private async Task ComputeNextMove() 
    { 
     // ... 
    } 
    // ... 
} 

这里,我将假定ComputeNextMove基本上是一个同步方法本身不打电话等待。这似乎与编译器警告的发布相矛盾(除非它是一个不好的例子......)

如果我没有在异步调用堆栈的END处调用.net异步方法,如HttpClient.GetStringAsync和I是否想要实现一些具体的“长时间运行”的同步逻辑,是否有更合适的方法来做到这一点?

也许我的假设是不正确的,并且ComputeNextMove可能被宣布为private void ComputeNextMove()这将不会产生警告。

+1

这是令人困惑的。你正在调用'Task.Run(Func )',它等待返回的任务。 – SLaks

+0

'任务'本身调用'await'。 – Jon

+0

“如果代码具有不等待的异步,则它是同步的” - 显示两个代码:“我认为它是同步的。”我迷路了。 – Magus

回答

12

是的,这只是一个不好的例子。

如果ComputeNextMove真正只是它并没有真正做任何事情异步(作为描述建议)同步方法,它不应该被声明为async。它应该是private void ComputeNextMove()

ComputeNextMove由于使用了Task.Run,它仍然会在后台线程上执行。

我将很可能使用一种方法团转化而不是这里的λ表达式:

await Task.Run((Action) ComputeNextMove); 
+0

感谢Jon,这可能是一个非常愚蠢的问题,但我见过的大多数示例都显示写了一个异步方法,它本质上调用了.net异步方法,并且我对_I_可能想要编写这种方法的情况有点模糊。根据响应(以及反编译'HttpClient.GetStringAsync')为例,它似乎归结为正在等待的某个任务。 – Novox

+0

@Novox:虽然它通常是,但并不总是一项任务。是的,相对较少的人会编写他们自己的“原始”异步方法。你通常最终会失败 - 可能通过许多其他的异步方法 - 框架*异步方法...或者为您在当前线程上不想执行的专门同步工作创建任务。 –

+0

在你的答案中,你使用方法组覆盖而不是lamba表达式。为什么这样 ?这样做是否有性能优势? –