【问题标题】:Close console application window after key press or automatically after x minutes按键后关闭控制台应用程序窗口或在 x 分钟后自动关闭
【发布时间】:2017-04-23 19:36:28
【问题描述】:

我在 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)。

那该怎么做呢?

【问题讨论】:

  • 您使用了错误类型的计时器,您不能在这样的控制台应用程序中使用System.Windows.Forms.Timer,您需要一个不依赖于“UI 线程”的计时器,例如 @ 987654323@

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


【解决方案1】:

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

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

这样,GUI 线程将有时间引发计时器的滴答事件。

【讨论】:

    【解决方案2】:

    您遇到的问题是您正在使用表单计时器,该计时器挂在 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);
        }
    

    【讨论】:

      【解决方案3】:

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

      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);
      }
      

      该解决方案的问题是这种类型的计时器是同步的,并且需要使用 Application.DoEvents,如 here 所述。此外,当 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);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-02
        • 1970-01-01
        • 1970-01-01
        • 2015-05-29
        相关资源
        最近更新 更多