【问题标题】:How can I await an async method without an async modifier in this parent method?如何在此父方法中等待没有异步修饰符的异步方法?
【发布时间】:2013-05-28 10:54:04
【问题描述】:

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

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
  }
}

这行不通,因为我必须在 Save() 的方法签名中添加“异步”,然后我不能返回 bool 我必须让它 Task&lt;bool&gt; 但我不希望任何人在等待Save() 方法。

有没有一种方法可以像 await 一样暂停代码执行,或者在没有 async 修饰符的情况下以某种方式等待这段代码?

【问题讨论】:

  • 如果你让我访问阻止我的线程的Save 方法,我会非常恼火,从而迫使我将调用包装在Task 中,这正是你可以返回的首先是我。只是说。

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


【解决方案1】:

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


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

要防止这种情况很难,但您可能应该始终通过调用 .Wait() 明确指定超时 - 以防万一。

【讨论】:

  • 谢谢,我正在使用 Task.Run - 我更新了我的问题以显示第二种方法
  • @Neal 进行编辑,我只想说“不要那样做”-您无缘无故地添加了一个线程。您不妨在将要等待的线程上执行该工作。
  • @Neal:Marc 完全正确;本质上,您在这里所做的是雇用某人代表您等待,然后等到他们完成工作,即代表您等待。在现实生活中你不会雇人来做这件事,所以不要在这里做。如果您需要同步等待任务完成,请这样做;如果你想在等待的时候继续工作,那么await它。
【解决方案2】:

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

这有点像问“我如何使用 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)位于应用程序的不同层(例如,数据/数据服务/视图模型)。数据/数据服务层不应进行同步/异步转换。视图模型(特定于应用程序的)级别是唯一有理由进行这种转换的级别——而且它应该只作为最后的手段。

【讨论】:

  • 如果我正在编写一个测试用例,将内容放入数据库(使用异步驱动程序),然后立即将其读回,该怎么办?只是说,同步编程有合法的用例。
  • @Hypershadsy:为什么不能异步执行?
  • 你可以写异步测试用例吗?
  • @Hypershadsy:是的。所有主要的单元测试框架(xUnit、MSTest、NUnit)都支持async Task单元测试方法since 2012
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多