假设我正在开发一个c#库,该库使用具有以下签名的接口,例如:
public interface IMyInterface
{
public void DoWork();
}
我有两个不同的类实现这个接口。
- 一个只运行同步代码(所以
void
返回类型将是好的)。 - 需要等待异步调用的一个(因此,理想情况下,我希望
DoWork
是async Task
,而不是void
)。
非异步类不是问题,因为它真正只需要一个void
返回类型:
public class NonAsyncClass : IMyInterface
{
public void DoWork()
{
Console.WriteLine("This is a non-Async method");
}
}
但我正在努力思考实现async
类的最佳方法。我在想这样的事情:
public class AsyncClass : IMyInterface
{
public void DoWork()
{
var t = Task.Run(async () => {
await ExternalProcess();
});
t.Wait();
}
}
但是感觉这不是正确的做事方式。
什么是最好的方法对一个接口程序(假设你没有更改任何控制的接口签名)void
返回类型的方法需要async
吗?反之亦然,当方法没有任何异步代码时,一个程序如何针对asyc Task
返回类型?
当方法需要异步时,针对具有void返回类型的接口(假设您无法控制更改任何接口签名)进行编程的最佳方法是什么?
这本质上和问"什么是阻塞异步代码的最好方法"是一样的,答案是一样的:没有最好的方法。正如我在MSDN的一篇文章中所描述的那样,有各种各样的破解方法,但没有一种破解方法适用于所有场景。
block -threadpool-hack (Task.Run(async () => await ExternalProcess()).GetAwaiter().GetResult();
)可能在大多数场景中工作;只有当ExternalProcess
必须访问与特定上下文相关的东西(例如,UI元素或HttpContext.Current
),或者它依赖于由一个线程一次上下文提供的隐式同步时,它才会失败。所以只要你的ExternalProcess
不需要一个特定的上下文,如果它是线程安全的,那么阻塞线程池hack应该工作。
反之亦然,当方法没有任何异步代码时,程序如何针对异步任务返回类型?
这个很简单。异步兼容(例如,Task
返回)接口方法意味着的实现可以是异步的,而不是它必须是异步的。同步实现可以使用Task.FromResult
和Task.FromException
来创建返回的Task
。或者,您可以将方法标记为async
并忽略编译器警告,这是我的AsyncEx库采用的方法。
如果ExternalProcess返回void,则不能对void使用await。编译器将告诉您何时尝试编译代码。因为interface.
如果ExternalProcess返回为"Task"数据类型你的代码必须工作良好。
在示例代码中不清楚。要将异步操作转换为同步操作?当用户调用DoWork方法时,程序将被阻塞,直到操作完成并继续执行下一行代码。