dotnet核心如何优雅地关闭子进程

时间:2019-05-16 05:45:24

标签: c# asp.net-core asp.net-core-webapi asp.net-core-2.2 windows-process

我有一个dotnet core 2.2控制台应用程序。
我将其托管为Windows服务。
服务启动另一个dotnet核心WebAPI。
问题是,服务停止后如何正常关闭WebAPI进程?
注意:我不想使用Kill()方法。

示例代码:

public class MyService : IHostedService, IDisposable
{
    private Timer _timer;
    static Process webAPI;

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _timer = new Timer(
            (e) => StartChildProcess(),
            null,
            TimeSpan.Zero,
            TimeSpan.FromMinutes(1));

        return Task.CompletedTask;
    }

    public void StartChildProcess()
    {
        try
        {
            webAPI = new Process();
            webAPI.StartInfo.UseShellExecute = false;
            webAPI.StartInfo.FileName = @"C:\Project\bin\Debug\netcoreapp2.2\publish\WebAPI.exe";
            webAPI.Start();
        }
        catch (Exception e)
        {
            // Handle exception
        }
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        // TODO: Add code to stop child process safely

        _timer?.Change(Timeout.Infinite, 0);

        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _timer?.Dispose();
    }
}

3 个答案:

答案 0 :(得分:0)

在github上有很多关于此问题的主题,请考虑发布7426

可在以下位置找到解决方案:StartAndStopDotNetCoreApp,program.cs的示例代码为:

using System;
using System.IO;
using System.Diagnostics;

namespace StartAndStopDotNetCoreApp
{
    class Program
    {
        static void Main(string[] args)
        {
            string projectPath = @"C:\source\repos\StartAndStopDotNetCoreApp\WebApplication";
            string outputPath = @"C:\Temp\WebApplication";

            Console.WriteLine("Starting the app...");
            var process = new Process();
            process.StartInfo.WorkingDirectory = projectPath;
            process.StartInfo.FileName = "dotnet";
            process.StartInfo.Arguments = $"publish -o {outputPath}";
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.CreateNoWindow = true;
            process.Start();
            process.WaitForExit();
            process.Close();
            process.Dispose();

            process = new Process();
            process.StartInfo.WorkingDirectory = outputPath;
            process.StartInfo.FileName = "dotnet";
            process.StartInfo.Arguments = $"{projectPath.Split(@"\")[projectPath.Split(@"\").Length - 1]}.dll";
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.CreateNoWindow = false;
            process.StartInfo.RedirectStandardOutput = true;

            process.Start();

            Console.WriteLine("Press anything to stop...");
            Console.Read();

            process.Kill();
        }
    }
}

如果这不是您想要的内容,请搜索提到的线程以寻求更多方法,它可以提供很多帮助。

答案 1 :(得分:0)

从技术上讲,您可以直接调用Process.Kill()来立即关闭该过程。但是,很多时间不是唯一可行的方法,因为WebAPI可能处于重要操作的中间,并且您无法真正分辨出何时可能发生这些操作,并且Process.Kill()并没有真正被认为是“优美的” “。

最明智的做法是告诉您您希望它 的过程,以便尽快关闭它,然后允许WebAPI在退出自身之前对其进行清理。如果您要设计的WebAPI更好,因为那样可以决定如何做。仅在绝对必要时才调用Kill()

您当然可以通过多种方式做到这一点。我想到的是一些套接字,这些套接字会定期检查并向WebAPI发送CTRL + C输入。


    public Task StopAsync(CancellationToken cancellationToken)
    {
        // send request to shut down

        // wait for process to exit and free its resources
        process.WaitForExit();
        process.Close();
        process.Dispose();



        _timer?.Change(Timeout.Infinite, 0);

        return Task.CompletedTask;
    }

当然,如果这是异步的,那么等待它退出方法内部就没有意义,因此您只需等待或检查它是否已退出该方法外部。

答案 2 :(得分:0)

也许可以使用CloseMainWindow类的System.Diagnostics.Process方法吗?当我在寻找一种从C#向其他进程发送WM_CLOSE消息的方法时,我偶然发现了它。

编辑:

CloseMainWindow如果主窗口被“阻塞”,例如被打开的模式窗口或对话框“阻塞”,则似乎不起作用。

您可能会研究一种将WM_CLOSE或WM_DESTROY消息显式发送到您的应用进程的策略。但是我不能保证它是否会按您的期望/预期工作。我已经很长时间没有使用这种Windows Messages功能了。