如何在此父方法中等待没有异步修饰符的异步方法?

Nea*_*eal 12 c# async-await .net-4.5

我有一个方法,我想等待,但我不想导致多米诺骨牌效应,认为任何东西都可以调用这个调用方法并等待它.例如,我有这个方法:

public bool Save(string data)
{
   int rowsAffected = await UpdateDataAsync(data);
   return rowsAffected > 0;
}
Run Code Online (Sandbox Code Playgroud)

我打电话给:

public Task<int> UpdateDataAsync()
{
  return Task.Run(() =>
  {
    return Data.Update(); //return an integer of rowsAffected
  }
}
Run Code Online (Sandbox Code Playgroud)

这将无法工作,因为我必须在方法签名中放入"async" Save(),然后我无法返回bool我必须做到Task<bool>但我不希望任何人等待该Save()方法.

有没有办法可以暂停代码执行,如等待或以某种方式等待没有async修饰符的代码?

Ste*_*ary 10

如何在此父方法中等待没有异步修饰符的异步方法?

这有点像问"如何使用C#编写应用程序,但不依赖于任何类型的.NET运行时?"

简短的回答:不要这样做.

真的,你在这里做的是采用一个自然同步的方法(Update),通过在线程池线程(UpdateDataAsync)上运行它看起来是异步的,然后你想要阻塞它以使异步方法看起来是同步的(Save).严重的红旗.

我建议你仔细研究斯蒂芬Toub著名的对博客文章的我应该公开异步包装我的同步方法我应该揭露同步包装我异步方法.两个问题的答案都是"不",尽管Stephen Toub解释了如果你真的必须这样做的几个选择.

"真的必须"应该保留给应用程序级别.我假设这些方法(Update,UpdateDataAsyncSave)位于应用程序的不同层(例如,数据/数据服务/视图模型).数据/数据服务层不应该进行同步/异步转换.视图模型(特定于应用程序)级别是唯一有借口进行这种转换的级别 - 它应该只作为最后的手段.


Mar*_*ell 5

编辑:这个答案是在Task.Run被添加之前。在这种额外的情况下,该场景最好被描述为“不要那样做”。


您可以访问.Result或使用.Wait(),但是您需要首先了解如何实现任务。特别是,您需要知道它是否使用同步上下文。之所以如此重要,是因为如果这样做会立即导致死锁,因为某些同步上下文需要调用上下文完全退出(例如,MVC的同步上下文需要离开控制器的action方法)。

要防止这种情况很难,但是为了防止.Wait()万一,您应该始终明确指定超时时间并调用。

  • @尼尔:马克绝对是对的;本质上,您在这里所做的就是雇用某人代表您等待,然后等到他们完成工作后再代表您等待。您不会雇用某人在现实生活中这样做,所以不要在这里这样做。如果您需要同步等待任务完成,则请等待;如果您想在等待时继续工作,请“等待”它。 (2认同)