【发布时间】:2020-06-09 13:22:37
【问题描述】:
我的情况是,我们有一些通过用户输入(按钮单击)运行的代码,这些代码通过一系列函数调用运行并导致生成一些数据(这是一个非常繁重的操作,需要几分钟) .我们想为此使用异步,这样它就不会在我们执行此操作时锁定 UI。
但同时我们也有一个要求,即这些函数也可以通过一个最好是同步的 API 来使用。
可视化/示例(伪代码):
public async void Button_Click() // from UI context
{
await instanceOfClassA.FuncA();
// some code
}
public async Task ClassA.FuncA()
{
await instanceOfClassB.FuncB()
// some code
}
public async Task ClassB.FuncB()
{
await instanceOfClassC.SomeHeavyFunc()
// some code
}
public async Task ClassC.SomeHeavyFunc()
{
// some heavy calculations
}
// Also need to provide a public synchronous API function
public void SomeClass.SynchronousAPIFunc()
{
// need to call differentInstanceOfClassB.FuncB()
}
有没有办法让公共 API 函数在内部等待异步操作?
编辑: 在此post 中,用户 Rachel 提供了该问题的两个答案。两者似乎都很有趣,但我不确定哪一个会提供最少的风险/副作用。
编辑2: 请注意,我们使用的是 .NET v4.6.1。
提前致谢。
【问题讨论】:
-
在 SomeClass.SynchronousAPIFunc() 你可以调用 differentInstanceOfClassB.FuncB().Result();这将导致方法 FuncB 被同步调用
-
这可以做到,但是很容易引入微妙的死锁。听起来你的要求很糟糕,如果不是荒谬的话
-
在这种情况下,通常最好过渡到基于队列或分布式工作流范式。如果您的 API 可以运行一个函数几分钟,通常调用框架会超时或将其解释为无响应。如果这个过程真的需要那么长时间,那么就改用 pub-sub 风格的架构。
-
最好从你的类中公开单独的异步/同步方法
-
@AluanHaddad 使用
.GetAwaiter().GetResult()具有相同的死锁风险,因此不再“安全”。它所做的只是解开异常。
标签: c# .net async-await