我有一组简单的代码,我试图在其中实现一个带有异步方法的接口。迄今为止的实现都是利用其异步部分并最终等待事物。然而,这个新的接口实现是一个简单的同步操作——不需要任何等待。
当我实现它时,首先感觉很奇怪。其次,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() 实现编写为同步签名有什么好处。
与异步方法的接口
从技术上讲,“一种返回的方法Task<T>”。async和await是实施细节。
返回可等待的方法是可能是异步的方法。同步返回已完成的任务是完全可以接受的。
执行此操作的一种方法是使用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使用线程池线程,在这种情况下不需要。