我为我正在开发的程序开发了一种简单的插件框架,作为其中的一部分,我有抽象基类,插件是从中派生出来的。例如:
public abstract class Plugin
{
public Task StartAsync()
{
Task.Run(Start);
}
protected abstract void Start();
}
问题在于,我真的希望能够等待StartAsync并在插件中完成所有内容(尽可能完成);很大程度上,我可以将所有内容包装在try-catch中,并避免插件取消我的应用程序(我意识到我应该使用应用程序域,如果必须,我会)。
在我使用异步Start方法定义插件之前,这一切都正常工作:
public class MyPlugin
{
protected override async void Start()
{
// await some awaitable stuff
}
}
当然,我的抽象基类不等待Start(因为它不知道它在编译时会异步)所以如果MyPlugin抛出异常,框架就没有机会捕获它。很明显,如果插件实现者做了一些非同步的异步,这也是正确的,但这似乎是一种非常简单的方法,只需在方法签名中添加异步,就可以自己动手。我意识到要求“等待等待”操作员是不合理的,但我想知道是否有人对如何摆脱这个问题有任何想法(或者它根本不是问题而且我是不合理的。)
这就是我想要在脑海中看到的内容:
public abstract class Plugin
{
public Task StartAsync()
{
Task.Run(() => awaitif Start());
}
protected abstract void Start();
}
最后,我宁愿不要使用Start async或返回一个Task,因为大多数插件可能都是简单和同步的。
答案 0 :(得分:2)
Task
- 接口中的返回方法与IDisposable
在设计上非常相似。
我宁愿不要使用Start async或返回一个Task,因为大多数插件可能都是简单和同步的。
事实是,某些的插件是异步的;因此,您应该有一个异步签名。在实现结束时,同步插件很容易return Task.FromResult(0)
。
考虑与IDisposable
的相似性:如果你的插件的某些是一次性的,你仍然应该从IDisposable
派生出来并且让非一次性插件实现空{ {1}}。