【问题标题】:console catch close event thread控制台捕获关闭事件线程
【发布时间】:2013-11-25 12:55:44
【问题描述】:

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

我正在尝试捕捉关闭事件并做一些事情。

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

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,而是应用程序崩溃。

有什么想法吗?

【问题讨论】:

  • 你能定义崩溃吗?事件日志/调试器中是否有任何堆栈跟踪/消息?
  • 我有一个 try/catch 块,但它并不止于此。相反,我收到带有此描述的弹出错误:“未知模块中发生'System.NullReferenceException'类型的未处理异常。附加信息:对象引用未设置为对象的实例。如果有此处理程序例外,该程序可以安全地继续进行。”输出窗口显示多行,并带有以下消息:“System.dll 中发生了 'System.ArgumentException' 类型的第一次机会异常”
  • 我的代码也发生了同样的事情。一个 backgroundWorker 和一个关闭事件,如果我在调用 DoWork 中的静态方法之前关闭程序,一切正常。很奇怪

标签: c# multithreading events console


【解决方案1】:

示例代码无法为我编译:

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

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

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

我尝试将示例程序类转换为全静态的。它没有在 Start() 方法中等待,因此我在 Start 方法的末尾添加了对 BackgroundWorker.IsBusy 的等待。 我还在回调中添加了这样的等待;否则,它只是一个竞赛,看看 doWork 方法的其余部分是否可以执行:

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

【讨论】:

    猜你喜欢
    • 2011-10-19
    • 1970-01-01
    • 2013-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多