只能运行同步时,请满足异步接口方法

时间:2017-10-04 05:59:08

标签: c# interface com async-await

我正在使用一个“API”(我使用松散的术语),它是作为COM +对象实现的。据我所知,COM +提供的任何排队功能都不支持,但我对COM +几乎一无所知。拿一粒盐。我只有一种方法可供我使用:invoke,并且它是同步的。

在一些有些个人才华的过程中,我在这个COM +对象周围创建了一个Web Api包装器,它只有一个端点,使用请求的post主体调用COM +对象。这使我可以异步调用Web Api(以及从我的应用程序中删除可怕的依赖)。

现在,我正在创建一个库来基本上抽象所有这些混乱,但我决定实现一个提供者模式,您可以选择直接使用COM +或Web Api包装器。显然,我有一个接口,包括同步和异步方法。 Web Api提供程序当然没有问题,因为您可以通过任何方式执行HTTP请求,但我正在使用COM +提供程序。因为异步不是那里的选择。

所以,我看到它有三个选项:

  1. 使用NotImplementedException“实现”异步接口方法,这违反了接口隔离原则。

  2. 做一些不明智的事情,比如使用Task.Run,我知道在这种情况下我并不是真的异步,而且基本上是任何针对我的图书馆编程的人。

  3. 执行诸如创建接口的同步和异步版本之类的操作,从接口隔离的角度来看,这更好,但从提供商模式的角度来看更糟糕。如果我依赖于异步接口,那么永远不能使用COM +提供程序,如果我依赖同步接口,那么我永远不能使用Web Api提供程序的异步方法。

  4. 长而短,我的一般问题是,在需要异步运行某些情况时,您会做什么,但您需要使用的方法只能同步运行?如果没有真正的替代方案,那么满足接口要求的最不具攻击性的方法是什么?

    修改

    我忘了再提一个选项:

    1. 在异步实现中调用方法同步,然后只返回Task.FromResult结果。这意味着我没有拉新线程(这可能是Web应用程序中的一个问题),但我不确定这是否真的比Task.Run更好,因为它向消费者说谎实际上是“异步”。

1 个答案:

答案 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块中。如果抛出异常,我们将需要返回一个包含该异常的错误任务。最后,如果它正确完成,我们将返回一个已完成的任务。