简体   繁体   English

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

[英]Satisfying an async interface method when you can only run sync

I'm consuming an "API" (I use the term loosely) that's implemented as a COM+ object.我正在使用作为 COM+ 对象实现的“API”(我松散地使用该术语)。 As far as I'm aware, there's no support for any of the queuing functionality COM+ offers, but I know pretty much exactly nil about COM+.据我所知,不支持 COM+ 提供的任何排队功能,但我对 COM+ 的了解几乎为零。 Take it with a grain of salt.把它和一粒盐一起吃。 I have just one method available to me: invoke , and it's sync.我只有一种方法可用: invoke ,它是同步的。

In a stroke of somewhat personal brilliance, I created a Web Api wrapper around this COM+ object, which has just one endpoint, invoking the COM+ object with the post body of the request.出于个人的聪明才智,我围绕这个 COM+ 对象创建了一个 Web Api 包装器,它只有一个端点,使用请求的 post 主体调用 COM+ 对象。 This has allowed me to make asynchronous calls to the Web Api instead (as well as remove the god-awful dependency from my apps).这使我可以改为对 Web Api 进行异步调用(以及从我的应用程序中删除可怕的依赖项)。

Now, I'm creating a library to basically abstract all this mess, but I decided to implement a provider pattern where you can choose to either use the COM+ directly or the Web Api wrapper.现在,我正在创建一个库来基本上抽象所有这些混乱,但我决定实现一个提供者模式,您可以选择直接使用 COM+ 或 Web Api 包装器。 I have an interface, obviously, with both sync and async methods.很明显,我有一个接口,包含同步和异步方法。 The Web Api provider is of course no problem as you can do an HTTP request either way, but I'm hitting a wall with the COM+ provider. Web Api 提供程序当然没问题,因为您可以通过任何一种方式执行 HTTP 请求,但是我与 COM+ 提供程序遇到了障碍。 Since async is not an option there.由于异步不是那里的选项。

So, I have three options as I see it:所以,在我看来,我有三个选择:

  1. "Implement" the async interface method with a NotImplementedException , which is a violation of the interface segregation principle. “实现”带有NotImplementedException的异步接口方法,这违反了接口隔离原则。

  2. Do something ill-advised like use Task.Run , which I know is not really async in this context, and basically lies to anyone programming against my library.做一些不明智的事情,例如使用Task.Run ,我知道在这种情况下它并不是真正的异步,并且基本上是针对针对我的库进行编程的任何人。

  3. Do something like create a sync and async version of the interface, which is better from a interface segregation standpoint, but worse from a provider pattern standpoint.做一些事情,比如创建接口的同步和异步版本,从接口隔离的角度来看更好,但从提供者模式的角度来看更糟。 If I depend on the async interface, then the COM+ provider can never be used, and if I depend on the sync interface, then I can never use the async methods of the Web Api provider.如果我依赖于异步接口,那么 COM+ 提供程序将永远无法使用,如果我依赖同步接口,那么我将永远无法使用 Web Api 提供程序的异步方法。

Long and short, my general question is what do you do in a situation where you need to run something asynchronously, but the method you need to utilize can only be run synchronously?总而言之,我的一般问题是,在需要异步运行某些东西但需要使用的方法只能同步运行的情况下,您会怎么做? If there's no real alternative, then what is the least offensive way to satisfy an interface requirement?如果没有真正的替代方案,那么满足接口要求的最不冒犯性的方法是什么?

EDIT编辑

I forgot to mention one more option:我忘了再提一个选项:

  1. Call the method sync inside the async implementation and then simply return Task.FromResult with the result.在异步实现中调用方法同步,然后简单地返回带有结果的Task.FromResult This means I'm not pulling a new thread (which could be an issue in a web application), but I'm not sure if this is really any better than Task.Run in the sense of lying to the consumer about this actually being "async".这意味着我不会拉新线程(这可能是 Web 应用程序中的一个问题),但我不确定这是否真的比Task.Run更好, Task.Run它实际上是向消费者撒谎“异步”。

The solution I landed on was to use Task.FromResult to return a Task even though nothing async is being done.我找到的解决方案是使用Task.FromResult返回一个Task即使没有进行任何异步操作。 While this is not actually async, it satisfies the interface.虽然这实际上不是异步的,但它满足接口。 I then commented the method to note that it will run sync and should be passed as a delegate to Task.Run in situations where the thread cannot be blocked (GUIs, for example).然后,我对该方法进行了注释,以指出它将运行同步,并且在无法阻止线程(例如 GUI)的情况下,应将其作为委托传递给Task.Run Using Task.Run is not appropriate in every situation (web applications, for one) and is an implementation detail that should be decided upon by the consumer of the library.使用Task.Run并不适用于所有情况(例如 Web 应用程序),它是一个实现细节,应该由库的使用者决定。

That said, to truly implement this, you need to handle three Task scenarios: completed, faulted, and cancelled.也就是说,要真正实现这一点,您需要处理三个Task场景:完成、故障和取消。 Here's the actual code to do all this:这是执行所有这些操作的实际代码:

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);
    }
}

First, this ensures that the operation hasn't been canceled.首先,这可确保操作未被取消。 If it has, a canceled task is returned.如果是,则返回已取消的任务。 Then, the sync work we need to do is wrapped in a try..catch block.然后,我们需要做的同步工作被包裹在一个 try..catch 块中。 If an exception is thrown, we'll need to return a faulted task, which includes that exception.如果抛出异常,我们需要返回包含该异常的错误任务。 Finally, if it completes correctly, we return a completed task.最后,如果它正确完成,我们返回一个已完成的任务。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 接口可以提供Sync和Async方法的方法吗? - Can a Interface provide methods for Sync and Async methods? 如何从同步方法运行异步方法(其中包含 try-catch(exception))? - How can I run an async method (that has inside it a try-catch(exception)) from a sync method? FTP上载在异步运行时不起作用,但在运行同步时起作用 - FTP upload not working when run async, but works when run sync 如何仅基于使用Roslyn的接口来识别方法实现是否标记为异步/可以异步调用? - How to identify if the method implementation is marked as async / can be called asynchronously, based only on its interface using Roslyn? 在Sync方法中调用Async - Calling Async in a Sync method 当虚拟方法不是异步时,覆盖方法的同步 - Αsync for overridden method when virtual method isn't async 如何在同步方法中调用异步方法? - How can I call an async method within a sync method? 如何使用通用方法实现接口? - How can you implement an interface with a generic method? 如何模拟返回接口的方法? - How can you mock a method that returns an interface? Redis Cache 获取同步请求超时和异步请求的缓慢响应仅在异步方法中 - Redis Cache getting timeout with sync requests and slow response with async requests only in async method
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM