C# 在只能运行同步时满足异步接口方法
我正在使用一个作为COM+对象实现的“API”(我松散地使用这个术语)。据我所知,COM+提供的任何排队功能都不支持,但我对COM+几乎一无所知。把它和盐一起吃。我只有一个方法可用:C# 在只能运行同步时满足异步接口方法,c#,interface,com,async-await,C#,Interface,Com,Async Await,我正在使用一个作为COM+对象实现的“API”(我松散地使用这个术语)。据我所知,COM+提供的任何排队功能都不支持,但我对COM+几乎一无所知。把它和盐一起吃。我只有一个方法可用:invoke,它是sync 在某种程度上,我个人才华横溢,围绕这个COM+对象创建了一个WebAPI包装器,它只有一个端点,通过请求的post主体调用COM+对象。这使我能够对Web Api进行异步调用(并从我的应用程序中删除可怕的依赖性) 现在,我正在创建一个库来基本上抽象所有这些混乱,但我决定实现一个提供程序模式
invoke
,它是sync
在某种程度上,我个人才华横溢,围绕这个COM+对象创建了一个WebAPI包装器,它只有一个端点,通过请求的post主体调用COM+对象。这使我能够对Web Api进行异步调用(并从我的应用程序中删除可怕的依赖性)
现在,我正在创建一个库来基本上抽象所有这些混乱,但我决定实现一个提供程序模式,您可以选择直接使用COM+或Web Api包装器。很明显,我有一个接口,同时具有sync和async方法。WebAPI提供程序当然没有问题,因为您可以通过任何一种方式执行HTTP请求,但我的COM+提供程序遇到了麻烦。因为异步不是一个选项
在我看来,我有三个选择:
NotImplementedException
“实现”异步接口方法,这违反了接口隔离原则Task.Run
,我知道在这种情况下,它不是真正的异步的,基本上对任何使用我的库编程的人都是谎言Task.FromResult
。这意味着我没有拉一个新线程(这可能是web应用程序中的一个问题),但我不确定这是否真的比任务好。运行,这是在欺骗消费者说这实际上是“异步的”
我找到的解决方案是使用
Task.FromResult
返回任务
,即使没有执行任何异步操作。虽然这实际上不是异步的,但它满足接口的要求。然后我对该方法进行了注释,指出它将运行sync,并应作为委托传递给任务。在无法阻止线程的情况下运行(例如GUI)。使用Task.Run
并非适用于所有情况(例如web应用程序),而是应由库的使用者决定的实现细节
也就是说,要真正实现这一点,您需要处理三种任务
场景:完成、故障和取消。下面是执行所有这些操作的实际代码:
public Task<int> DoSomethingAsync(CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
{
return Task.FromCanceled<int>(cancellationToken);
}
try
{
return Task.FromResult<int>(DoSomething());
}
catch (Exception e)
{
return Task.FromException<int>(e);
}
}
public Task DoSomethingAsync(CancellationToken CancellationToken)
{
if(cancellationToken.IsCancellationRequested)
{
返回任务.fromCancelled(cancellationToken);
}
尝试
{
返回Task.FromResult(DoSomething());
}
捕获(例外e)
{
返回任务.FromException(e);
}
}
首先,这确保操作没有被取消。如果有,则返回已取消的任务。然后,我们需要做的同步工作被包装在一个try..catch块中。如果抛出异常,我们将需要返回一个出错的任务,其中包括该异常。最后,如果它正确完成,我们将返回一个已完成的任务。除了2,我在这里看不到合理的选择。如果你真的不能改变COM的一面,你就不必“撒谎”,这是一个不取决于你的事实,你会尽你最大的努力把行为隐藏起来。如果你能改变它:是的,不,不能改变。不幸的是,它是由我们的POS(这在很大程度上意味着销售点和其他东西)提供商作为“API”提供的第三方DLL。它一直是偏头痛的根源。Task.Run()非常异步。但是COM有一个特性,对象可以告诉操作系统它不是线程安全的。倾向于有用,比它每天以完全不可诊断的方式在你没有源代码的代码中随机崩溃一次要好。当你有确凿的证据证明一个库不是线程安全的,而这样的库从来都不是线程安全的时,你真的必须担心线程安全。给我一个机会。