我在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)。
那怎么办呢?
答案 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);
}