首页 > 解决方案 > .net Core 控制台应用程序 - 退出信号有一个硬停止时间

问题描述

我有许多需要构建的控制台应用程序都运行“工作”。它们将是长期运行的过程——永无止境,而且它们不断地工作。

考虑到这一点,我希望建立一种通用的方式来托管这些工作。每个都将是一个控制台应用程序,但不是使用 Console.Read() 之类的东西来停止控制台应用程序完成,而是使用 ManualResetEventSlim 来阻止该过程完成。

我提出了一个通用接口,每个控制台应用程序都将实现它,然后它可以以通用方式运行。如下:

public interface IHostedProcess
{
    void Starting();
    void Run();
    void Stopping();
}

这意味着我可以使用启动、运行和停止方法来实现托管进程的通用方法:

public class ProcessHost
{
    ManualResetEventSlim keepAliveEvent = new ManualResetEventSlim();

    public void Run(IHostedProcess hostedProcess)
    {
        hostedProcess.Starting();

        AssemblyLoadContext.Default.Unloading += async ctx =>
        {
            hostedProcess.Stopping();
            keepAliveEvent.Set();
        };

        hostedProcess.Run();
        keepAliveEvent.Wait();
    }
}

以及一个实现 IHostedProcess 接口并可以在控制台应用程序中运行的类的简单示例:

public class MyHostedProcess : IHostedProcess
{
    public void Starting()
    {
        Console.WriteLine("Job starting");

        // Call my custom code here...
    }

    public void Run()
    {
        Console.WriteLine("Job running");

        // Call my custom code here...
    }

    public void Stopping()
    {
        Console.WriteLine("Job stopping1");

        // Call my custom code here...
    }
}

让我的控制台应用程序代码如下所示:

public static void Main(string[] args)
{
    try
    {
        var mp = new MyHostedProcess();

        var ph = new ProcessHost();
        ph.Run(mp);
    }
    catch (Exception e)
    {
        Console.WriteLine("Something went wrong! " + e.Message);
        throw;
    }
}

输出如下:

在此处输入图像描述

然后单击“X”停止该过程:

在此处输入图像描述

我们看到“停止”消息:

在此处输入图像描述

所以这一切都可以正常工作,直到某一点 - 当我尝试执行长时间运行的关闭过程时,MyHostedProcess.Stopping它似乎有一个硬关闭,而不是等到该过程完成。例如,将“停止”过程修改为:

public void Stopping()
{
    Console.WriteLine("Job stopping first");

    // Call my custom code here...
    Thread.Sleep(20000); // Doesnt seem to wait this long...
    Console.WriteLine("Job stopping second"); // Never see this!
}

我从来没有看到“工作停止秒”输出,因为控制台应用程序似乎在 10 秒左右后硬停止。我究竟做错了什么?如何更优雅地处理关机并保证我可以在应用关闭之前完成任何关机工作?也许有一种方法可以做到我错过的“开箱即用”?

感谢您提前提供任何指示!

标签: c#.net-coreconsole-applicationapplication-shutdownmanualresetevent

解决方案


推荐阅读