【发布时间】:2018-03-15 10:30:46
【问题描述】:
我正在使用一个作为 COM+ 对象实现的“API”(我使用松散的术语)。据我所知,不支持 COM+ 提供的任何排队功能,但我对 COM+ 几乎一无所知。带上一粒盐。我只有一种方法可用:invoke,它是同步的。
出于某种个人才华,我围绕这个 COM+ 对象创建了一个 Web Api 包装器,它只有一个端点,使用请求的 post 正文调用 COM+ 对象。这让我可以改为对 Web Api 进行异步调用(以及从我的应用程序中删除可怕的依赖项)。
现在,我正在创建一个库来基本上抽象所有这些混乱,但我决定实现一个提供者模式,您可以选择直接使用 COM+ 或 Web Api 包装器。显然,我有一个带有同步和异步方法的接口。 Web Api 提供程序当然没有问题,因为您可以通过任何一种方式发出 HTTP 请求,但我在 COM+ 提供程序上遇到了麻烦。由于那里没有异步选项。
所以,在我看来,我有三个选择:
用
NotImplementedException“实现”异步接口方法,这违反了接口隔离原则。做一些不明智的事情,比如使用
Task.Run,我知道在这种情况下它并不是真正的异步,并且基本上对任何针对我的库进行编程的人都是谎言。创建接口的同步和异步版本之类的操作,从接口隔离的角度来看更好,但从提供者模式的角度来看更糟。如果我依赖异步接口,则永远无法使用 COM+ 提供程序,如果我依赖同步接口,则永远无法使用 Web Api 提供程序的异步方法。
总之,我的一般问题是,在您需要异步运行某些东西,但您需要使用的方法只能同步运行的情况下,您会怎么做?如果没有真正的替代方案,那么满足接口要求的最不冒犯的方式是什么?
编辑
我忘了再提一个选项:
- 在异步实现中调用方法同步,然后简单地返回
Task.FromResult和结果。这意味着我不会拉新线程(这可能是 Web 应用程序中的一个问题),但我不确定这是否真的比Task.Run更好,因为它实际上是在向消费者撒谎“异步”。
【问题讨论】:
-
我在这里除了2之外没有看到合理的选择。如果你真的不能改变COM端,你不必“撒谎”,这是不取决于你的事实,您尽最大努力将行为包装在下面。如果可以更改:msdn.microsoft.com/en-us/library/windows/desktop/ms692623.aspx
-
是的,不,无法更改。不幸的是,它是我们的 POS(这在很大程度上意味着销售点和其他东西)提供商提供的第三方 DLL,作为“API”。它一直是偏头痛的根源。
-
Task.Run() 是相当异步的。但是 COM 具有对象可以告诉操作系统它不是线程安全的特性。往往是有用的,比它在你没有源代码的代码中以完全无法诊断的方式每天随机崩溃一次要好。当你有确凿的证据证明一个库不是线程安全的时,你真的不得不担心线程安全,这样的库从来都不是。只需给它一个safe home。
标签: c# interface com async-await