使用同步代码实现异步接口

sco*_*gen 1 c# asynchronous

我有一组简单的代码,我试图在其中实现一个带有异步方法的接口。迄今为止的实现都是利用其异步部分并最终等待事物。然而,这个新的接口实现是一个简单的同步操作——不需要任何等待。

当我实现它时,首先感觉很奇怪。其次,Visual Studio 确认了我的不安,并发出警告,告诉我该方法将同步运行——这正是我所期望的,但警告告诉我它对 VS 来说也很糟糕。我应该遵循更好的模式吗?

public interface IActivity
{
    async Task<bool> DoStuff();
}

//...

List<IActivity> activities = new List<IActivity>(){
   new SynchronousActivityA(),
   new SynchronousActivityB(),
   new AsynchronousActivityC()
};

foreach (var activity in activities){
    bool stuff = await activity.DoStuff();
    //do things with stuff.
}
Run Code Online (Sandbox Code Playgroud)

我可以让我的 DoStuff() 实现执行如下操作:

await Task.Run(() => DoStuffSynchronously());
Run Code Online (Sandbox Code Playgroud)

这将使我的警告消失并感觉更“正确”,但我不确定这比仅仅将 DoStuff() 实现编写为同步签名有什么好处。

Ste*_*ary 8

与异步方法的接口

从技术上讲,“一种返回的方法Task<T>”。asyncawait是实施细节。

返回可等待的方法是可能是异步的方法。同步返回已完成的任务是完全可以接受的。

执行此操作的一种方法是使用Task.FromResult,但您还希望确保捕获异常并将其返回到任务中:

try { return Task.FromResult(DoStuffSynchronously()); }
catch (Exception ex) { return Task.FromException<bool>(ex); }
Run Code Online (Sandbox Code Playgroud)

这话有点罗嗦了。async它本质上与without做同样的事情await,但是你需要#pragma去掉警告消息,这也很尴尬。如果您经常这样做,您可能需要为其定义一个实用方法,就像TaskHelper.ExecuteAsTask在我的AsyncEx 库中一样。

您不应该Task.Run仅仅使用“使代码异步”。Task.Run使用线程池线程,在这种情况下不需要。