我有一个我想等待的方法,但是我不想引起多米诺骨牌效应,以为任何东西都可以调用此调用方法并等待它。例如,我有此方法:
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运行时?”
简短的答案:不要那样做。
真的,您在这里所做的是采用自然同步的方法(Update
),通过在线程池线程(UpdateDataAsync
)上运行它,使它看起来像是异步的,然后您想要阻塞它使异步方法显示为同步(Save
)。严重的红旗。
[我建议您仔细研究Stephen Toub著名的一对博客文章should I expose asynchronous wrappers for my synchronous methods和should I expose synchronous wrappers for my asynchronous methods。这两个问题的答案都是“否”,尽管史蒂芬·图卜(Stephen Toub)解释了一些您确实需要这样做的选择。
“必须”必须保留给应用程序级别。我假设这些方法(Update
,UpdateDataAsync
和Save
)位于应用程序的不同层中(例如,数据/数据服务/视图模型)。数据/数据服务层不应进行同步/异步转换。视图模型(特定于应用程序)级别是唯一有借口进行这种转换的级别,并且只能作为最后的选择。
编辑:此答案在添加Task.Run之前。在这种额外的情况下,该场景最好被描述为“不要那样做”。
您可以访问.Result
或使用.Wait()
,但您需要先了解如何实现任务。特别是,您需要知道它是否使用同步上下文。之所以如此重要,是因为如果这样做会立即导致死锁,因为某些同步上下文需要调用上下文退出completely(例如,MVC的同步上下文需要离开控制器的action方法)。
为了防止这种情况很难,但是您可能应该始终通过调用.Wait()
明确指定超时,以防万一。