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

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

public bool Save(string data) { int rowsAffected = await UpdateDataAsync(data); return rowsAffected > 0; } 

我打电话给:

 public Task UpdateDataAsync() { return Task.Run(() => { return Data.Update(); //return an integer of rowsAffected } } 

这将无法工作,因为我必须在Save()的方法签名中放入“async”然后我不能返回bool我必须使它成为Task但我不希望任何人等待Save()方法。

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

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

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

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

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

我建议你仔细研究Stephen Toub着名的博客文章, 如果我为我的同步方法公开异步包装器,我 应该为我的异步方法公开同步包装器 。 这两个问题的答案都是“不”,尽管Stephen Toub解释了如果你真的需要这样做的几个选择。

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

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


您可以访问.Result或使用.Wait() ,但您需要先了解该任务的实现方式。 特别是,您需要知道它是否使用同步上下文。 这很重要的原因是,如果它这样做,这可能会立即死锁,因为一些sync-contexts需要调用上下文完全退出(例如,MVC的sync-context需要离开控制器的action方法)。

要防止这种情况很难,但你应该总是通过调用.Wait()来明确指定超时 – 以防万一。