我正在使用一个“API”(我使用松散的术语),它是作为COM +对象实现的。据我所知,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
更好,因为它向消费者说谎实际上是“异步”。答案 0 :(得分:1)
我登陆的解决方案是使用Task.FromResult
返回Task
,即使没有执行异步操作。虽然这实际上并不是异步,但它满足了界面。然后我评论了方法,注意它将运行同步,并且应该在无法阻塞线程的情况下(例如,GUI)作为委托传递给Task.Run
。使用Task.Run
并不适用于所有情况(Web应用程序,一个),并且是应由库的使用者决定的实现细节。
也就是说,要真正实现这一点,您需要处理三个Task
场景:已完成,出现故障和已取消。以下是完成所有这些操作的实际代码:
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);
}
}
首先,这确保了操作尚未取消。如果有,则返回已取消的任务。然后,我们需要做的同步工作包含在try..catch块中。如果抛出异常,我们将需要返回一个包含该异常的错误任务。最后,如果它正确完成,我们将返回一个已完成的任务。