2013-11-01 82 views
0

我为我正在开发的程序开发了一种简单的插件框架,并且作为它的一部分,我有抽象基类,插件意味着从中派生出来。例如:避免覆盖中的异步问题

public abstract class Plugin 
{ 
    public Task StartAsync() 
    { 
     Task.Run(Start); 
    } 

    protected abstract void Start(); 
} 

美中不足的是,我真的很希望能够等待StartAsync和拥有一切完成(尽可能)的插件;很大程度上,我可以将所有内容都包含在try-catch中,并避免插件取消我的应用程序(我意识到我应该使用应用程序域,如果必须,我会)。

这是直到我在插件中定义的具有异步启动方法都工作正常:

public class MyPlugin 
{ 
    protected override async void Start() 
    { 
     // await some awaitable stuff 
    } 
} 

当然,我的抽象基类不等待启动(因为它不知道它会在编译时是异步的),所以如果MyPlugin抛出一个异常,框架没有机会去捕捉它。很显然,如果插件实现者做了一些异步的事情,但是这看起来像是一种非常简单的方式,只需在方法签名中添加异步,就可以轻松地完成自己的脚步。我意识到要求“等待,如果等待”操作员是不合理的,但我想知道是否有人对如何摆脱这个问题有任何想法(或者它不是一个问题,我也不合理)。

这里就是我想在我的脑海看到:

public abstract class Plugin 
{ 
    public Task StartAsync() 
    { 
     Task.Run(() => awaitif Start()); 
    } 

    protected abstract void Start(); 
} 

最后,我宁可不要让启动异步或返回任务,因为大多数的插件将可能是简单和同步。

+1

这就是为什么你不使用'async void'方法。调用者无法知道操作何时完成,或者是否有任何错误。这是没有办法的;你需要返回一个'Task'(或其他具有相同信息的东西)给调用者来处理它。 – Servy

+0

@Servy是的,这可能是公平的。但是,我无法阻止实施者指定异步。如果答案是,只需将[NotAsync]放在方法上,我会很高兴。 – Jeff

+0

没有AppDomain,插件将会非常困难。祝你好运:) –

回答

2

Task接口中的返回方法在设计上与IDisposable非常相似。

我宁愿不开始异步或返回一个任务,因为大多数插件将可能是简单和同步的。

事实上,你的插件的一些是异步的;因此,你应该有一个异步签名。在实施结束时,对return Task.FromResult(0)同步插件很容易。

考虑相似IDisposable:如果您插件的一些是一次性的,你还是应该从IDisposable获得,只是有非一次性的插件实现空Dispose

+0

太棒了,我并不知道FromResult。干杯。 – Jeff