C# 避免覆盖中的异步问题

C# 避免覆盖中的异步问题,c#,.net,asynchronous,async-await,C#,.net,Asynchronous,Async Await,我为我正在开发的一个程序开发了一种简单的插件框架,作为它的一部分,我有一些抽象的基类,插件就是从这些基类派生出来的。例如: public abstract class Plugin { public Task StartAsync() { Task.Run(Start); } protected abstract void Start(); } 问题是我真的希望能够等待StartAsync,并在插件中完成所有事情(尽可能);很大程度上,我可以把

我为我正在开发的一个程序开发了一种简单的插件框架,作为它的一部分,我有一些抽象的基类,插件就是从这些基类派生出来的。例如:

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抛出异常,框架就没有机会捕获它。显然,如果插件实现者做了一些不被期待的异步操作,这也是正确的,但是这似乎是一种非常简单的方法,只需将异步添加到方法签名中,就可以让您一败涂地。我意识到要求一个“wait if waitable”接线员是不合理的,但我想知道是否有人想过如何让自己摆脱这个问题(或者这根本不是问题,我是不合理的)

以下是我试图在脑海中看到的:

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

    protected abstract void Start();
}

最后,我不希望使Start异步或返回任务,因为大多数插件可能是简单和同步的。

任务
-接口中的返回方法在设计上与
IDisposable
非常相似

我不希望使Start异步或返回任务,因为大多数插件都可能是简单和同步的

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


考虑与
IDisposable
的相似性:如果您的一些插件是一次性的,那么您仍然应该从
IDisposable
派生,只让非一次性插件实现一个空的
Dispose

这就是为什么您不使用
异步void
方法的原因。调用方无法知道操作何时完成,或者是否有任何错误。这是没有办法的;您需要返回一个
任务
(或其他具有相同信息的任务),以便调用方处理。@Servy是的,这可能是公平的。但是,我不能阻止实现者指定async。如果答案是,只要在方法上加上[NotAsync],我会很高兴的。没有AppDomains插件将非常困难。祝你好运:)你不应该让
Async
方法仅仅在线程池上运行同步工作。是的,我已经解决了,谢谢!太棒了,我不知道结果。干杯