我的程序需要在关闭前做一些简单的操作,在网上搜到可以用SetConsoleCtrlHandler这个方法。部分代码:using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.IO;
namespace ConsoleColsed
{
    public delegate bool ConsoleCtrlDelegate(int dwCtrlType);
    public class ClsMain
    {
        public static StreamWriter sw;        [DllImport("kernel32.dll")]
        static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate HandlerRoutine, bool Add);
        //当用户关闭Console时,系统会发送次消息
        const int CtrlC = 0;
        const int CTRL_CLOSE_EVENT = 2;
        const int CTRL_LOGOFF_EVENT = 5;
        const int CTRL_SHUTDOWN_EVENT = 6;        public static void Main()
        {
            sw = new StreamWriter("close.txt");
            sw.WriteLine("Test started at " + DateTime.Now.ToString("hh:mm:ss"));
            ClsMain cls=new ClsMain();
            Console.WriteLine("start");
            //
            // 其他代码。
            //
            Console.Read();
            sw.Close();
        }        public ClsMain()
        {
            ConsoleCtrlDelegate newDelegate=new ConsoleCtrlDelegate(HandlerRoutine);
            GC.KeepAlive(newDelegate);
            SetConsoleCtrlHandler(newDelegate, true);
        }        public static bool HandlerRoutine(int CtrlType)
        {
            switch (CtrlType)
            {
                case CTRL_CLOSE_EVENT:
                    sw.WriteLine("user close");
                    break;
                case CTRL_LOGOFF_EVENT: 
                    sw.WriteLine("log off");
                    break;
                case CTRL_SHUTDOWN_EVENT:
                    sw.WriteLine("shut down");
                    break;
            }
            sw.WriteLine("Test stopped at " + DateTime.Now.ToString("hh:mm:ss"));
            sw.Close();            return false;
        }
    }
}测试时发现,如果运行较短时间(十几分钟内)后手动关闭,可以正常处理结束。但如果运行时间较长,比如超过一个小时,关闭就出现异常,会弹出Windows无法结束程序的对话框。请高手看看什么原因,多谢了。“其他代码”部分主要是不断的用IE打开不同的网页,然后关闭,其中用了大量的System.Threading.Thread.Sleep(),而且有很多写文件的操作。但整个程序完全是单线程的。如果把其他代码部分全部去掉,只留下 Console.Read();超过一个小时还是可以正常处理关闭事件。

解决方案 »

  1.   

    虽然你在HandlerRoutine写了“sw.Close();”,也不能保证程序立刻能够停下来。
    几个小时的测试我就不做了,给你几个方案你试一下。
    一、在其他代码执行部分加个判断,每次开始一个新的操作前先判断一个变量的值,运行继续执行的才执行,否则就停止执行,该值在HandlerRoutine中设置关闭。
    二、去掉这行代码“ClsMain cls=new ClsMain();”后看看还会不会出现关不掉程序的情况。
      

  2.   


    1,这个方法基本没用。因为程序的大部分时间处于Sleep状态。“其他代码”大致是一个循环,运行几秒钟,然后会Sleep(100)秒。
    2,这行不能去,因为“其他代码”还有很多初始化的工作。 这个函数也会有影响?
      

  3.   

    关闭时发现最后的HandlerRoutine没有运行。出现异常:
    Unhandled Exception: System.AccessViolationException: Attempted to read or write
     protected memory. This is often an indication that other memory is corrupt.
      

  4.   

    为了帮你这个忙,我好好研究了下,现在问题找到了,你把Main函数部分改成这样应该就可以了:        public static void Main()
            {
                sw = new StreamWriter("close.txt");
                sw.WriteLine("Test started at " + DateTime.Now.ToString("hh:mm:ss"));            ConsoleCtrlDelegate newDelegate = new ConsoleCtrlDelegate(HandlerRoutine);
                SetConsoleCtrlHandler(newDelegate, true);
                
                Console.WriteLine("start");            //
                // 其他代码。
                
                Console.Read();
                sw.Close();
                GC.KeepAlive(newDelegate);
            }