反复启动和停止工作者服务 修改1 编辑2更新

如何解决反复启动和停止工作者服务 修改1 编辑2更新

此项目中有两个文件program.cs用于操作服务,而worker.cs包含服务逻辑。 在program.cs内部,我使用以下方法操作服务:

// program.cs (partially)
public static void Main(string[] args)
{
    while (true)
    {
        string a = client.ReceiveFrameString();  // To receive a flag from external programs to start the service
        if (bool.Parse(a))
        {
            Console.WriteLine("START");
            Thread t = new Thread(new ParameterizedThreadStart(ThreadProc));
            t.Start(args);
            CreateHostBuilder(args).Build().RunAsync().Wait(); // This works at the first start
            // ATTENTION! CreateHostBuilder(args).Build().Run() will return an error about args.Length < 0
            Console.WriteLine("DONE Start");
        }
    }
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureServices((hostContext,services) =>
                {
                    services.AddHostedService<Worker>();
                });
public static void ThreadProc(object obj)
{
    string[] args = ToStringArray(obj);
    while (true)
    {
        string temp = recv.ReceiveFrameString();  // To receive a flag from external programs to stop the service
        if (!bool.Parse(temp))
        {
            Console.WriteLine("STOP");
            CreateHostBuilder(args).Build().StopAsync().Wait();
            Console.WriteLine("DONE Stop");
            break;  // Jump out of the loop as soon as the service is stopped.
        }
    }
}

如您所见,我正在使用一个while循环来创建一个“ Start-Stop”集,其中包含启动服务的命令和一个从外部源触发时停止服务的线程。我可以根据如下BackgroundService类中被覆盖的StartAsync和StopAsync方法中的日志输出观察服务是否已成功启动和停止:

// worker.cs (partially)
public override async Task StartAsync(CancellationToken cancellationToken)
{
    _logger.Loginformation("STARTED!!");
    await base.StartAsync(cancellationToken);
}
public override async Task StopAsync(CancellationToken cancellationToken)
{
    _logger.Loginformation("STOPPED!!");
    await base.StopAsync(cancellationToken);
}

现在,启动服务的命令在第一次触发时起作用,但是在成功调用线程后,StopAsync无法按预期方式起作用。

作为预期结果,我希望该服务能够反复启动和停止。那有什么问题呢?并且有解决方案吗?

修改1

最小可重复的示例是located here.

编辑2(更新)

经过几天关于堆栈溢出和MSDN的研究,我终于找到了适用于我的方案的解决方案。

首先,根据this answer,我确定我的应用程序不是长期服务,因此我删除了Worker中的“ repeat-until-your-BackgroundService-is-stopped”循环服务模板:

// From worker.cs
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    // Remove the while loop
    /*while (!stoppingToken.IsCancellationRequested)
    {
        // _logger.Loginformation("Worker running at: {time}",DateTimeOffset.Now);
        // await Task.Delay(1000,stoppingToken);
    }*/
}

第二,根据this MSDN C# API about RunAsync(IHost,CancellationToken),我可以创建一个CancellationSource,它可以生成CancellationToken来取消它。与the example given in the documentation类似,我可以通过取消源关闭工作程序。因此,实现变为:

// From program.cs
public static void Main(string[] args)
{
    while (true)
    {
        string a = client.ReceiveFrameString();  // To receive a flag from external programs to start the service
        if (bool.Parse(a))
        {
            Console.WriteLine("START");
            CancellationTokenSource source = new CancellationTokenSource();
            CancellationToken token = source.Token;
            Thread t = new Thread(new ParameterizedThreadStart(ThreadProc));
            t.Start(source);
            CreateHostBuilder(args).Build().RunAsync(token);
            Console.WriteLine("DONE Start");
        }
    }
}
public static void ThreadProc(object obj)
{
    var source = obj as CancellationTokenSource;
    while (true)
    {
        string temp = recv.ReceiveFrameString();  // To receive a flag from external programs to stop the service
        if (!bool.Parse(temp))
        {
            Console.WriteLine("STOP");
            source.Cancel();
            source.dispose();
            Console.WriteLine("DONE Stop");
            break;  // Jump out of the loop as soon as the service is stopped.
        }
    }
}

但是,此解决方案不适用于带有“重复直到您的BackgroundService已停止”循环的工作人员。似乎CancellationToken无法触发worker.cs中ExecuteAsync内部的取消请求。现在应该问这个问题:如何使用“重复-直到您的BackgroundService-is-stopped”循环启动和停止辅助服务? The original Minimal Producible Example was adjusted according to the EDIT 2 now.

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

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?