如何以编程方式在 asp.net 核心中重新启动应用程序?
我想清除缓存并导致应用程序重新进入启动状态。
在你阅读我的答案之前: 此解决方案将停止应用程序并导致应用程序在下一个请求中重新进入启动。
.NET Core 2有时您可能希望强制您的 ASP.Net Core 2站点以编程方式回收。即使在MVC/WebForms时代,这也不一定是推荐的做法,但唉,有一种方法。ASP.Net Core 2 允许注入一个 IApplicationLifetime
对象,让您做一些方便的事情。首先,它将允许您注册启动,关闭和关闭的事件,类似于过去可能通过Global.asax
获得的事件。但是,它还公开了一种允许您关闭站点的方法(没有黑客攻击!您需要将其注入您的网站,然后只需调用它即可。下面是一个控制器示例,其路由将关闭站点。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
namespace MySite.Controllers
{
public class WebServicesController : Controller
{
private IApplicationLifetime ApplicationLifetime { get; set; }
public WebServicesController(IApplicationLifetime appLifetime)
{
ApplicationLifetime = appLifetime;
}
public async Task ShutdownSite()
{
ApplicationLifetime.StopApplication();
return "Done";
}
}
}
来源: http://www.blakepell.com/asp-net-core-ability-to-restart-your-site-programatically-updated-for-2-0
更新:Mirask的答案对于.NET Core 2更正确。
在"程序"中.cs您将看到对host.Run()
的调用。 此方法具有接受System.Threading.CancellationToken
的重载。 这就是我正在做的:
public class Program {
private static CancellationTokenSource cancelTokenSource = new System.Threading.CancellationTokenSource();
public static void Main(string[] args) {
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run(cancelTokenSource.Token);
}
public static void Shutdown() {
cancelTokenSource.Cancel();
}
}
然后,在我的控制器中,我可以调用Program.Shutdown()
,几秒钟后应用程序就会死亡。 如果它位于 IIS 后面,则另一个请求将自动启动应用程序。
ASP.NET Core 3+
由于接受的答案是使用IApplicationLifetime
,而 ASP.NET Core 3 以后已经过时,因此新的推荐方法是使用位于 Microsoft.Extensions.Hosting
命名空间中的IHostApplicationLifetime
。
在我的 Blazor 应用程序中,我可以使用以下代码:
@inject IHostApplicationLifetime AppLifetime
<button @onclick="() => AppLifetime.StopApplication()">Restart</button>
对于 .NET Core 2.2,可以使用以下代码:
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using System.Threading;
namespace BuildMonitor
{
public class Program
{
private static CancellationTokenSource cancelTokenSource = new System.Threading.CancellationTokenSource();
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();
host.RunAsync(cancelTokenSource.Token).GetAwaiter().GetResult();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
public static void Shutdown()
{
cancelTokenSource.Cancel();
}
}
}
例如,可以将服务器关闭放在某个网页后面:
using System;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace BuildMonitor.Pages
{
public class StopServerModel : PageModel
{
public void OnGet()
{
Console.WriteLine("Forcing server shutdown.");
Program.Shutdown();
}
}
}
stopServer.bat 例如可以像这样:
@echo off
rem curl http://localhost:5000/StopServer >nul 2>&1
powershell.exe -Command (new-object System.Net.WebClient).DownloadString('http://localhost:5000/StopServer') >nul
exit /b 0
上面的解决方案都没有达到我想要的效果。这就是我想出的:
public class Program
{
private static CancellationTokenSource cts = new CancellationTokenSource();
private static string[] _args;
private static bool _restartRequest;
public static async Task Main(string[] args)
{
_args = args;
await StartServer();
while (_restartRequest)
{
_restartRequest = false;
Console.WriteLine("Restarting App");
await StartServer();
}
}
public static void Restart()
{
_restartRequest = true;
cts.Cancel();
}
private static async Task StartServer()
{
try
{
cts = new CancellationTokenSource();
await CreateHostBuilder(_args).RunConsoleAsync(cts.Token);
}
catch (OperationCanceledException e)
{
Console.WriteLine(e);
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
如果你只需要一个开发场景,那么你可以使用dotnet-watch(对于dotnet)或dnx-watch(对于dnx)。
如果希望应用程序在生产中重新启动,则必须实现类似于观察程序执行的操作。您需要一个外部进程来终止并重新启动该进程。或者,您需要您的应用程序启动自身的实例,然后杀死自己。不幸的是,这没有什么开箱即用的。
Dotnet 7.0。当不在 IIS 后面工作时,这是一个快速的黑客。停止应用程序并获取正在运行的进程路径以在同一终端窗口中重新启动进程。
public MyController(ILogger<MyController> logger, Microsoft.AspNetCore.Hosting.IApplicationLifetime appLifetime)
{
this.logger = logger;
this.appLifetime = appLifetime;
}
/// <summary>
/// Restarts the API
/// </summary>
[HttpPost("Restart")]
public async Task<int> Restart()
{
appLifetime.StopApplication();
string _currentProcess = Path.GetFullPath(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
Process.Start(_currentProcess);
return await Task.FromResult(0);
}