dotnet core 如何优雅地关闭子进程
dotnet core how to shutdown child process gracefully
我有一个 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();
}
}
github 上有很多关于此问题的话题,请考虑 post 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();
}
}
}
如果这不是您要查找的内容,请搜索提到的线程以获取更多方法,它提供了很多方法。
从技术上讲,您只需调用 Process.Kill()
即可立即关闭进程。但是,很多时候这并不是正确的方法,因为 WebAPI 可能正处于重要操作的中间,您无法真正判断这些操作何时可能发生并且 Process.Kill()
并未真正考虑 "graceful".
最谨慎的做法是告诉进程您喜欢让它在方便的时候尽早关闭,然后让 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;
}
当然,如果这是 Async,那么等待它在方法内部退出是没有意义的,因此您只需等待或检查它是否已在该方法外部退出。
也许可以使用System.Diagnostics.Process
class的CloseMainWindow
方法?我在寻找一种从 C# 向另一个进程发送 WM_CLOSE 消息的方法时偶然发现了它。
编辑:
如果主要 window 是 "blocked",CloseMainWindow
似乎不起作用,例如通过打开模式 window 或对话框。
您可能会研究一种向您的应用进程显式发送 WM_CLOSE 或 WM_DESTROY 消息的策略。但我不能保证它是否会像你一样工作want/expect。我已经很长时间没有使用那种 Windows 消息功能了。
我有一个 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();
}
}
github 上有很多关于此问题的话题,请考虑 post 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();
}
}
}
如果这不是您要查找的内容,请搜索提到的线程以获取更多方法,它提供了很多方法。
从技术上讲,您只需调用 Process.Kill()
即可立即关闭进程。但是,很多时候这并不是正确的方法,因为 WebAPI 可能正处于重要操作的中间,您无法真正判断这些操作何时可能发生并且 Process.Kill()
并未真正考虑 "graceful".
最谨慎的做法是告诉进程您喜欢让它在方便的时候尽早关闭,然后让 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;
}
当然,如果这是 Async,那么等待它在方法内部退出是没有意义的,因此您只需等待或检查它是否已在该方法外部退出。
也许可以使用System.Diagnostics.Process
class的CloseMainWindow
方法?我在寻找一种从 C# 向另一个进程发送 WM_CLOSE 消息的方法时偶然发现了它。
编辑:
如果主要 window 是 "blocked",CloseMainWindow
似乎不起作用,例如通过打开模式 window 或对话框。
您可能会研究一种向您的应用进程显式发送 WM_CLOSE 或 WM_DESTROY 消息的策略。但我不能保证它是否会像你一样工作want/expect。我已经很长时间没有使用那种 Windows 消息功能了。