23

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

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()方法。

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

4

2 回答 2

13

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

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

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

实际上,您在这里所做的是采用自然同步方法 ( Update),通过在线程池线程 () 上运行它使其看起来异步UpdateDataAsync,然后您想要阻止它以使异步方法看起来同步( Save)。严重的危险信号。

我建议您仔细研究 Stephen Toub 的著名博客文章,我是否应该为我的同步方法公开异步包装器,以及我是否应该为我的异步方法公开同步包装器。这两个问题的答案都是“不”,尽管如果你真的必须这样做,斯蒂芬图布解释了几个选择。

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

于 2013-06-01T23:07:58.857 回答
11

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


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

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

于 2013-06-01T21:20:42.457 回答