控制台捕获关闭事件线程

时间:2013-11-25 12:55:44

标签: c# multithreading events console

我有一个控制台应用程序,它使用BackgroundWorker来运行无限循环。

我正试图捕捉近距离事件并做一些事情。

我使用了一些google搜索解决方案,并提出了以下建议:

class Program
{
   private static bool keepAlive = false;
   private static BackgroundWorker bgWorker = new BackgroundWorker();

   private static void runThread ()
   {
       while (keepAlive) {}
   }

   private bool ConsoleClosingCheck(CtrlTypes ctrlType)
   {
       switch (ctrlType)
       {
           case CtrlTypes.CTRL_CLOSE_EVENT:
               keepAlive = false;
               break;
       }
       return true;
   }

   [DllImport("Kernel32")]
   public static extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, bool Add);

   public delegate bool HandlerRoutine(CtrlTypes CtrlType);

   public enum CtrlTypes
   {
       CTRL_C_EVENT = 0,
       CTRL_BREAK_EVENT,
       CTRL_CLOSE_EVENT,
       CTRL_LOGOFF_EVENT = 5,
       CTRL_SHUTDOWN_EVENT
   }

   public static void Start ()
   {
       keepAlive = true;
       bgWorker.DoWork += (sender, e) => runThread();
       bgWorker.RunWorkerAsync();

   }

   public static void Main(string[] args)
   {
       Program p = new Program();

       SetConsoleCtrlHandler(new HandlerRoutine(p.ConsoleClosingCheck), true);

       p.Start();
   }
}   

当我调试它并使用“X”(正常关闭)关闭控制台时,它不会停在case,而是应用程序崩溃。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

示例代码不能为我编译:

Member 'Program.Start()' cannot be accessed with an instance reference;

我怀疑问题只是因为您创建的'p'对象没有托管根(没有托管类保留对它的引用),只有一个非托管回调引用它。

这意味着p可以收集垃圾,在调用回调时导致失败。

我尝试将示例Program类转换为静态。它没有在Start()方法中等待,所以我在start方法结束时添加了对BackgroundWorker.IsBusy的等待。 我还在回调中添加了这样的等待;否则,它只是一场比赛,看看doWork方法的其余部分是否可以执行:

case CtrlTypes.CTRL_CLOSE_EVENT:
{
    keepAlive = false;
    while (bgWorker.IsBusy)
    {
        Thread.Sleep(100);
    }
    break;
}