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

时间:2013-06-01 21:08:08

标签: c# .net-4.5 async-await

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

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

我打电话:

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

这不会起作用,因为我必须把#as;&#34; async&#34;在Save()的方法签名中然后我无法返回bool我必须Task<bool>但我不想让任何人等待Save()方法

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

3 个答案:

答案 0 :(得分:10)

  

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

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

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

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

我建议您仔细研究Stephen Toub着名的一对博文should I expose asynchronous wrappers for my synchronous methodsshould I expose synchronous wrappers for my asynchronous methods。两个问题的答案都是“不”,尽管Stephen Toub解释了如果你真的需要这样做的几个选择。

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

答案 1 :(得分:4)

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


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

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

答案 2 :(得分:0)

我之所以来到这里是因为强调了Resharper。这不是问题的答案,但可以节省一些时间。

如果您不需要返回值,则可以使用丢弃:

 var _ = UpdateDataAsync(data);