按键后关闭控制台应用程序窗口或x分钟后自动关闭

时间:2017-04-23 19:36:28

标签: c# visual-studio-2008 timer console-application

我在Visual Studio 2008,C#和.NET Framework 3.5中有一个控制台应用程序。

当应用程序完成所有操作时,我想在用户按键时关闭窗口,或者在几分钟后自动关闭窗口。

所以在我的申请结束时我做了:

static System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();

public static int Main(string[] args)
{
   // Do some stuff
   Console.WriteLine("Press any key to close this window.");

   myTimer.Tick += new EventHandler(TimerEventProcessor);
   myTimer.Interval = 5000;
   myTimer.Start();

   Console.ReadKey();

   return 0;
}


private static void TimerEventProcessor(Object myObject, EventArgs myEventArgs)       
{
    myTimer.Stop();
    Environment.Exit(0);
}

这里的问题是窗口在x分钟过后没有关闭,甚至从未提出定时器事件,因为程序被阻塞等待一个键(ReadKey)。

那怎么办呢?

3 个答案:

答案 0 :(得分:1)

尝试将要完成的工作转移到一个单独的线程中:

public static int Main(...)
{
    new System.Threading.Thread(Work).Start();
}
private void Work()
{
    // work to be done here
}

这样GUI线程就有时间提升计时器的tick事件。

答案 1 :(得分:1)

你遇到的问题是你正在使用一个表单计时器,它挂在UI线程上 - 用于控制台应用程序。您正在退出非控制台的环境。

我们需要使用线程计时器。但是,这应该没有太大的不同。

    static Timer myTimer;

    public static int Main(string[] args)
    {
        // Do some stuff
        Console.WriteLine("Press any key to close this window.");

        //Hey, I just met you and this is crazy
        myTimer = new Timer(CallMeMaybe, null, 5000, 0);

        //so call me maybe
        Console.ReadKey();

        return 0;
    }

    //Instead of a tick, we have this
    private static void CallMeMaybe(object state)
    {
        //But here's my number
        Environment.Exit(0);
    }

答案 2 :(得分:0)

我找到了一个可能的解决方案,但不确定是否最好:

static System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();

public static int Main(string[] args)
{
   // Do some stuff
   Console.WriteLine("Press any key to close this window.");

   myTimer.Tick += new EventHandler(TimerEventProcessor);
   myTimer.Interval = 5000;
   myTimer.Start();

   // while (!Console.KeyAvailable)
   //{
   //     Application.DoEvents();
   //     Thread.Sleep(250);
   //}

   // Above code replaced with:
   Console.ReadKey(true);

   DisposeTmr();

   return 0;
}

private static void DisposeTmr() 
{
    myTimer.Stop();
    myTimer.Dispose();
}

private static void TimerEventProcessor(Object myObject, EventArgs myEventArgs)       
{
    DisposeTmr();
    Environment.Exit(0);
}

该解决方案的问题是这种类型的计时器是同步的,需要按照here的说明使用Application.DoEvents。当UI线程处于休眠状态时,计时器仍处于挂起状态,因此这可能导致计时器事件处理程序在主UI线程处于休眠状态时不继续捕获计时器事件。

为避免这种情况,有两个选项,System.Timers.Timer和System.Threading.Timer。我已经实现了System.Threading.Timer解决方案,如下所示,它完美地运行:

static System.Threading.Timer myTimer;

public static int Main(string[] args)
{
   // Do some stuff
   Console.WriteLine("Press any key to close this window.");

   myTimer = new System.Threading.Timer(TimerCallback, null, 5000, Timeout.Infinite);

   while (!Console.KeyAvailable)
   {          
        Thread.Sleep(250);
   }

   DisposeTmr();

   return 0;
}

private static void DisposeTmr() 
{
    if (myTimer != null)
    {
        myTimer.Dispose();
    }
}

private static void TimerCallback(Object myObject)       
{
    DisposeTmr();
    Environment.Exit(0);
}