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

问题描述 投票:13回答:2

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

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<bool>,但我不希望任何人等待Save()方法。

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

c# .net-4.5 async-await
2个回答
11
投票

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

有点像问“如何使用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)位于应用程序的不同层中(例如,数据/数据服务/视图模型)。数据/数据服务层不应进行同步/异步转换。视图模型(特定于应用程序)级别是唯一有借口进行这种转换的级别,并且只能作为最后的选择。


5
投票

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


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

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

© www.soinside.com 2019 - 2024. All rights reserved.