fix infinite loop when pressed ctrl+c

This commit is contained in:
cs8425
2026-04-28 21:09:14 +08:00
parent 3eca16a661
commit 34b93ad55d
3 changed files with 49 additions and 19 deletions

View File

@@ -148,13 +148,29 @@ public class IConsole
#endregion #endregion
public static string ListenConsole() public static async Task ListenConsole(CancellationToken exitToken)
{ {
while (true) while (!exitToken.IsCancellationRequested)
{ {
ConsoleKeyInfo keyInfo; ConsoleKeyInfo keyInfo;
try { keyInfo = Console.ReadKey(true); } try
catch (InvalidOperationException) { continue; } {
if (!Console.KeyAvailable)
{
await Task.Delay(10, exitToken);
continue;
}
keyInfo = Console.ReadKey(true);
}
catch (OperationCanceledException)
{
break;
}
catch (InvalidOperationException)
{
await Task.Delay(50, exitToken);
continue;
}
switch (keyInfo.Key) switch (keyInfo.Key)
{ {

View File

@@ -160,7 +160,7 @@ public class LoaderManager : MikuSB
} }
} }
public static void InitCommand() public static async Task InitCommand(CancellationToken exitToken)
{ {
// Register the command handlers // Register the command handlers
try try
@@ -178,6 +178,6 @@ public class LoaderManager : MikuSB
IConsole.OnConsoleExcuteCommand += CommandExecutor.ConsoleExcuteCommand; IConsole.OnConsoleExcuteCommand += CommandExecutor.ConsoleExcuteCommand;
CommandExecutor.OnRunCommand += (sender, e) => { CommandManager.HandleCommand(e, sender); }; CommandExecutor.OnRunCommand += (sender, e) => { CommandManager.HandleCommand(e, sender); };
IConsole.ListenConsole(); await IConsole.ListenConsole(exitToken);
} }
} }

View File

@@ -18,6 +18,10 @@ public class MikuSB
public static readonly Listener Listener = new(); public static readonly Listener Listener = new();
public static readonly CommandManager CommandManager = new(); public static readonly CommandManager CommandManager = new();
// for exit signal
private static readonly CancellationTokenSource _cts = new();
private static int _exitCode = 0;
public static async Task Main() public static async Task Main()
{ {
var time = DateTime.Now; var time = DateTime.Now;
@@ -50,11 +54,15 @@ public class MikuSB
ResourceManager.IsLoaded = true; ResourceManager.IsLoaded = true;
HandbookGenerator.GenerateAll(); HandbookGenerator.GenerateAll();
LoaderManager.InitCommand(); var consoleTask = Task.Run(() => LoaderManager.InitCommand(_cts.Token), _cts.Token);
var elapsed = DateTime.Now - time; var elapsed = DateTime.Now - time;
Logger.Info(I18NManager.Translate("Server.ServerInfo.ServerStarted", Logger.Info(I18NManager.Translate("Server.ServerInfo.ServerStarted",
Math.Round(elapsed.TotalSeconds, 2).ToString(CultureInfo.InvariantCulture))); Math.Round(elapsed.TotalSeconds, 2).ToString(CultureInfo.InvariantCulture)));
await consoleTask;
ProcessExit(Volatile.Read(ref _exitCode));
} }
#region Exit #region Exit
@@ -64,30 +72,36 @@ public class MikuSB
AppDomain.CurrentDomain.ProcessExit += (_, _) => AppDomain.CurrentDomain.ProcessExit += (_, _) =>
{ {
Logger.Info(I18NManager.Translate("Server.ServerInfo.Shutdown")); Logger.Info(I18NManager.Translate("Server.ServerInfo.Shutdown"));
ProcessExit(); RequestShutdown(0);
}; };
AppDomain.CurrentDomain.UnhandledException += (obj, arg) => AppDomain.CurrentDomain.UnhandledException += (obj, arg) =>
{ {
Logger.Error(I18NManager.Translate("Server.ServerInfo.UnhandledException", obj.GetType().Name), Logger.Error(I18NManager.Translate("Server.ServerInfo.UnhandledException", obj.GetType().Name),
(Exception)arg.ExceptionObject); (Exception)arg.ExceptionObject);
Logger.Info(I18NManager.Translate("Server.ServerInfo.Shutdown")); Logger.Info(I18NManager.Translate("Server.ServerInfo.Shutdown"));
ProcessExit(); RequestShutdown(1);
Environment.Exit(1);
}; };
Console.CancelKeyPress += (_, eventArgs) => Console.CancelKeyPress += (_, eventArgs) =>
{ {
Logger.Info(I18NManager.Translate("Server.ServerInfo.CancelKeyPressed")); Logger.Info(I18NManager.Translate("Server.ServerInfo.CancelKeyPressed"));
eventArgs.Cancel = true; eventArgs.Cancel = true;
Environment.Exit(0); RequestShutdown(0);
}; };
} }
private static void ProcessExit() private static void RequestShutdown(int exitCode)
{
Interlocked.Exchange(ref _exitCode, exitCode);
_cts.Cancel();
}
private static void ProcessExit(int exitCode)
{ {
SocketListener.Connections.Values.ToList().ForEach(x => x.Stop(true)); SocketListener.Connections.Values.ToList().ForEach(x => x.Stop(true));
DatabaseHelper.SaveThread?.Interrupt(); DatabaseHelper.SaveThread?.Interrupt();
DatabaseHelper.SaveDatabase(); DatabaseHelper.SaveDatabase();
Environment.Exit(exitCode);
} }
# endregion # endregion