我需要将程序的执行延迟指定的毫秒数,但也希望用户能够在按下某个键时转义等待。如果没有按下任何键,程序应该等待指定的毫秒数。
我一直在使用Thread.Sleep
暂停程序(在我的程序上下文中我觉得没问题,因为UI在主方法执行期间设置为最小化)。
我考虑过做这样的事情:
while(GetAsyncKeyState(System.Windows.Forms.Keys.Escape) == 0 || waitTime > totalWait)
{
Thread.Sleep(100);
waitTime += 100;
}
由于Thread.Sleep
将等到至少在唤醒线程之前指定的时间,因此在while循环中放大时显然会有很大的不必要的额外延迟。 / p>
是否有某种方法会在指定的时间内睡眠,但只有在条件成立的情况下?或者上面的例子是“正确”的方法,但使用更准确的睡眠方法?如果是这样,我可以使用哪种方法?
提前感谢您的帮助。
编辑----可能的想法......
DateTime timeAtStart = DateTime.Now;
int maxWaitTime = 15000;
while (true)
{
if (GetAsyncKeyState(System.Windows.Forms.Keys.Escape) != 0)
{
break;
}
if ((DateTime.Now - timeAtStart).TotalMilliseconds >= maxWaitTime)
{
break;
}
}
这不使用任何类型的计时器,但看起来它可以工作,任何建议?
编辑2:以上对我有用,现在允许我在按下转义时中断等待。我注意到延迟比使用Thread.Sleep
更准确!
答案 0 :(得分:3)
考虑颠倒概念......而不是延迟它一段时间,考虑在某个时间开始执行,或者按下某个键。< / p>
使用tick处理程序启动Windows窗体计时器,它将启动您想要发生的任何事情,还将启动它并停止计时器的键事件处理程序。
答案 1 :(得分:2)
第一个示例使用Timer,ManuelResetEvent和Global Keyboard hook:
我没有包含键盘钩子代码,因为它太大了。你可以找到它here。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
namespace WindowsFormsApplication1
{
static class Program
{
private static System.Threading.Timer _timer;
private static ManualResetEvent _signal;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
_signal = new ManualResetEvent(false);
_timer = new System.Threading.Timer(Timer_Signaled, null, 15000, 0);
_signal.WaitOne();
_signal.Reset();
Application.Run(new Form1());
}
private static void Timer_Signaled(object state)
{
_signal.Set();
}
}
}
当您挂机键盘并按下ESC时,只需调用:_signal.Set()。第一个样本只是为了给你一个想法。
第二个样本:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
static class Program
{
[DllImport("user32.dll")]
static extern short GetAsyncKeyState(System.Windows.Forms.Keys vKey);
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
int maxWaitTime = 15000;
int tc = System.Environment.TickCount;
while (true)
{
System.Threading.Thread.Sleep(1000);
if (System.Environment.TickCount - tc > maxWaitTime)
{
break;
}
if (GetAsyncKeyState(Keys.Escape) > 0)
{
break;
}
}
Application.Run(new Form1());
}
}
}
编辑:
第一个示例更可靠,因为键盘钩子使用回调来通知哪个键被按下了。第二个样本就像“拉”一样,并且可能不会收集每个按键。
答案 2 :(得分:0)
查看您的代码,我假设您正在使用Windows窗体用于UI。
有很多方法可以解决您的问题,但鉴于框架最容易让我想到的是:
this.Enabled = false
)timer.Tick += ContinueUITimer();
)this.KeyDown += ContinueUIKeyboard
)使用这样的ContinueUI函数:
void ContinueUIXxx(...)
{
timer.Tick -= ContinueUITimer;
this.KeyDown -= ContinueUIKeyboard;
this.Enabled = true;
... whatever else in the continuation;
}