微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 用于确保给定类型的单个未完成任务的模式

考虑以下:

public class SomeService
{
    public Task StartAsync()
    {
        return Task.Factory
            .StartNew(() => DoStartup());
    }

    public Task StopAsync()
    {
        return Task.Factory
            .StartNew(() => DoShutdown());
    }
}

上述问题是,如果多次调用StartAsync或StopAsync,则将创建多个任务来启动/停止服务.实际上,人们只希望一次启动一个启动/停止任务.为此,我通常做这样的事情:

public class SomeService
{
    private readonly object startSync = new object();
    private readonly object stopSync = new object();
    private Task startTask;
    private Task stopTask;

    public Task StartAsync()
    {
        var startTaskLocal = this.startTask;

        if (startTaskLocal != null)
        {
            return startTaskLocal;
        }

        lock (this.startSync)
        {
            if (this.startTask != null)
            {
                return this.startTask;
            }

            this.startTask = Task.Factory
                .StartNew(() => DoStartup())
                .Then(x =>
                    {
                        lock (this.stopSync)
                        {
                            this.stopTask = null);
                        }
                    });

            return this.startTask;
        }
    }

    public Task StopAsync()
    {
        // similar pattern to above
    }
}

现在虽然这有效,但它有点难看.在我试图将这种模式封装成小而可重复使用的东西之前,我已经走得太远了,我想知道是否有一种已经建立的方式这样做我不知道?

PS.我通过让StartAsync等待任何未完成的StopAsync调用来进一步扩展这个想法,反之亦然.这意味着任何时候都只能进行一次启动或停止操作.通过任务组合很容易做到这一点.如果我可以首先找出是否已经建立了完全实现上述目标的方法,那么我可以弄清楚它是否适合这种扩展行为.

解决方法

您可以使用 State Machine pattern.当代码进入AsyncStart时,将状态设置为Starting.我建议将对象的状态设置为Running的回调.

为Stopping,Stopped提供相同的功能.

因此,您的服务内部可能有一个ServiceState对象.在调用AsyncStart / AsyncStop之前,请检查当前状态.

更新
…另一种方式可能是存储和检查Cancellation Token.有关如何使用CancellationToken的无数样本.这只是我的头脑,而不是确认这是最好的方式.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐