꽤 많은 스레드가 포함 된 콘솔 응용 프로그램이 있습니다. 특정 조건을 모니터링하고 참일 경우 프로그램을 종료하는 스레드가 있습니다. 이 종료는 언제든지 발생할 수 있습니다.
다른 모든 스레드를 정리하고 모든 파일 핸들과 연결을 제대로 닫을 수 있도록 프로그램이 닫힐 때 트리거 될 수있는 이벤트가 필요합니다. .NET 프레임 워크에 이미 빌드 된 것이 있는지 확실하지 않으므로 직접 작성하기 전에 묻습니다.
다음과 같은 이벤트가 있는지 궁금합니다.
MyConsoleProgram.OnExit += CleanupBeforeExit;
답변
웹에서 코드를 어디에서 찾았는지 모르겠지만 지금은 이전 프로젝트 중 하나에서 찾았습니다. 이렇게하면 콘솔에서 정리 코드를 수행 할 수 있습니다. 예를 들어 갑자기 닫히거나 종료로 인해 …
[DllImport("Kernel32")]
private static extern bool SetConsoleCtrlHandler(EventHandler handler, bool add);
private delegate bool EventHandler(CtrlType sig);
static EventHandler _handler;
enum CtrlType
{
CTRL_C_EVENT = 0,
CTRL_BREAK_EVENT = 1,
CTRL_CLOSE_EVENT = 2,
CTRL_LOGOFF_EVENT = 5,
CTRL_SHUTDOWN_EVENT = 6
}
private static bool Handler(CtrlType sig)
{
switch (sig)
{
case CtrlType.CTRL_C_EVENT:
case CtrlType.CTRL_LOGOFF_EVENT:
case CtrlType.CTRL_SHUTDOWN_EVENT:
case CtrlType.CTRL_CLOSE_EVENT:
default:
return false;
}
}
static void Main(string[] args)
{
// Some biolerplate to react to close window event
_handler += new EventHandler(Handler);
SetConsoleCtrlHandler(_handler, true);
...
}
최신 정보
의견을 확인하지 않는 사람들에게는이 특정 솔루션이 Windows 7 에서 잘 작동 하지 않는 것 같습니다 (또는 전혀) . 다음 스레드 는 이것에 대해 이야기합니다.
답변
전체 작업 예제는 ctrl-c로 작업하고 X로 창을 닫고 종료합니다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
namespace TestTrapCtrlC {
public class Program {
static bool exitSystem = false;
#region Trap application termination
[DllImport("Kernel32")]
private static extern bool SetConsoleCtrlHandler(EventHandler handler, bool add);
private delegate bool EventHandler(CtrlType sig);
static EventHandler _handler;
enum CtrlType {
CTRL_C_EVENT = 0,
CTRL_BREAK_EVENT = 1,
CTRL_CLOSE_EVENT = 2,
CTRL_LOGOFF_EVENT = 5,
CTRL_SHUTDOWN_EVENT = 6
}
private static bool Handler(CtrlType sig) {
Console.WriteLine("Exiting system due to external CTRL-C, or process kill, or shutdown");
//do your cleanup here
Thread.Sleep(5000); //simulate some cleanup delay
Console.WriteLine("Cleanup complete");
//allow main to run off
exitSystem = true;
//shutdown right away so there are no lingering threads
Environment.Exit(-1);
return true;
}
#endregion
static void Main(string[] args) {
// Some boilerplate to react to close window event, CTRL-C, kill, etc
_handler += new EventHandler(Handler);
SetConsoleCtrlHandler(_handler, true);
//start your multi threaded program here
Program p = new Program();
p.Start();
//hold the console so it doesn’t run off the end
while (!exitSystem) {
Thread.Sleep(500);
}
}
public void Start() {
// start a thread and start doing some processing
Console.WriteLine("Thread started, processing..");
}
}
}
답변
또한 확인 :
AppDomain.CurrentDomain.ProcessExit
답변
비슷한 문제가 있었는데, 내 콘솔 앱이 중간에 하나의 선점 문이있는 무한 루프에서 실행될 것입니다. 내 해결책은 다음과 같습니다.
class Program
{
static int Main(string[] args)
{
// Init Code...
Console.CancelKeyPress += Console_CancelKeyPress; // Register the function to cancel event
// I do my stuffs
while ( true )
{
// Code ....
SomePreemptiveCall(); // The loop stucks here wating function to return
// Code ...
}
return 0; // Never comes here, but...
}
static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
Console.WriteLine("Exiting");
// Termitate what I have to terminate
Environment.Exit(-1);
}
}
답변
스레드가 응용 프로그램을 직접 종료하는 것 같습니까? 애플리케이션이 종료되어야한다는 것을 알리기 위해 스레드가 메인 스레드에 신호를 보내는 것이 더 낫습니다.
이 신호를 받으면 메인 스레드는 다른 스레드를 완전히 종료하고 마지막으로 자신을 종료 할 수 있습니다.
답변
ZeroKelvin의 답변은 Windows 10 x64, .NET 4.6 콘솔 앱에서 작동합니다. CtrlType 열거 형을 다룰 필요가없는 사람들을 위해 다음은 프레임 워크 종료에 연결하는 매우 간단한 방법입니다.
class Program
{
private delegate bool ConsoleCtrlHandlerDelegate(int sig);
[DllImport("Kernel32")]
private static extern bool SetConsoleCtrlHandler(ConsoleCtrlHandlerDelegate handler, bool add);
static ConsoleCtrlHandlerDelegate _consoleCtrlHandler;
static void Main(string[] args)
{
_consoleCtrlHandler += s =>
{
//DoCustomShutdownStuff();
return false;
};
SetConsoleCtrlHandler(_consoleCtrlHandler, true);
}
}
핸들러에서 FALSE를 반환하면 프레임 워크에 제어 신호를 “처리”하지 않고이 프로세스의 핸들러 목록에있는 다음 핸들러 함수가 사용됩니다. TRUE를 반환하는 처리기가 없으면 기본 처리기가 호출됩니다.
사용자가 로그 오프 또는 종료를 수행하면 콜백이 Windows에서 호출되지 않고 대신 즉시 종료됩니다.
답변
WinForms 앱이 있습니다.
Application.ApplicationExit += CleanupBeforeExit;
콘솔 앱의 경우
AppDomain.CurrentDomain.DomainUnload += CleanupBeforeExit;
그러나 어떤 시점에서 호출되는지 또는 현재 도메인 내에서 작동하는지 확실하지 않습니다. 나는 그렇지 않다고 생각한다.