代码之家  ›  专栏  ›  技术社区  ›  Chris Pratt

当您只能运行sync时,满足异步接口方法

  •  1
  • Chris Pratt  · 技术社区  · 7 年前

    invoke ,它是同步的。

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

    在我看来,我有三个选择:

    1. 使用 NotImplementedException

    2. Task.Run ,我知道在这种情况下它并不是真正的异步的,并且基本上对任何针对我的库编程的人来说都是错误的。

    3. 做一些类似于创建接口的同步和异步版本的事情,这从接口隔离的角度来看更好,但从提供程序模式的角度来看更糟糕。如果我依赖于异步接口,则永远不能使用COM+提供程序,如果我依赖于同步接口,则永远不能使用Web Api提供程序的异步方法。

    长话短说,我的一般问题是,在需要异步运行某些东西,但需要使用的方法只能同步运行的情况下,您会怎么做?如果没有真正的替代方案,那么满足接口需求的最不冒犯的方式是什么?

    编辑

    我忘了再提一个选项:

    1. 在异步实现内调用方法sync,然后简单地返回 Task.FromResult 结果是。这意味着我并没有引入新的线程(这可能是web应用程序中的一个问题),但我不确定这是否真的比 任务跑 在向消费者撒谎说这实际上是“异步”的意义上。
    1 回复  |  直到 7 年前
        1
  •  1
  •   Chris Pratt    7 年前

    我找到的解决方案是使用 Task.FromResult 返回 Task 即使没有异步操作。虽然这实际上不是异步的,但它满足了接口。然后我对该方法进行了注释,指出它将运行sync,并应作为委托传递给 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);
        }
    }
    

    首先,这可以确保操作没有被取消。如果有,则返回已取消的任务。然后,我们需要做的同步工作被包装在一个try中。。挡块。如果引发异常,我们需要返回一个出错的任务,其中包括该异常。最后,如果它正确完成,我们将返回一个已完成的任务。