如何将程序延迟一定的毫秒数,或直到按下某个键? [英] How to delay program for a certain number of milliseconds, or until a key is pressed?

查看:36
本文介绍了如何将程序延迟一定的毫秒数,或直到按下某个键?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将我的程序执行延迟指定的毫秒数,但还希望用户能够在按下某个键时避免等待.如果没有按下任何键,程序应等待指定的毫秒数.

I need to delay my program's execution for a specified number of milliseconds, but also want the user to be able to escape the wait when a key is pressed. If no key is pressed the program should wait for the specified number of milliseconds.

我一直在使用 Thread.Sleep 来停止程序(在我的程序上下文中,我认为这没问题,因为在执行 main 方法期间 UI 设置为最小化).

I have been using Thread.Sleep to halt the program (which in the context of my program I think is ok as the UI is set to minimise during the execution of the main method).

我曾考虑过做这样的事情:

I have thought about doing something like this:

while(GetAsyncKeyState(System.Windows.Forms.Keys.Escape) == 0 || waitTime > totalWait)
{
    Thread.Sleep(100);
    waitTime += 100;
}

由于 Thread.Sleep 将等待 至少 指定的时间,然后再唤醒线程,显然会有很大的不必要的额外延迟,因为它在while 循环.

As Thread.Sleep will wait until at least the time specified before waking the thread up, there will obviously be a large unwanted extra delay as it is scaled up in the while loop.

是否有某种方法可以休眠指定的时间,但仅在条件成立时才休眠?或者上面的例子是正确"的方法,而是使用更准确的睡眠方法?如果可以,我可以使用什么方法?

Is there some sort of method that will sleep for a specified amount of time but only while a condition holds true? Or is the above example above the "correct" way to do it but to use a more accurate Sleep method? If so what method can I use?

预先感谢您的帮助.

编辑----可能的想法...

Edit ---- Possible Idea...

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

这不使用任何类型的计时器,但看起来可以工作,有什么建议吗?

This doesn't use any sort of timer but looks like it could work, any suggestions?

编辑 2:以上对我有用,现在允许我在按下转义键时打破等待.我注意到延迟也比使用 Thread.Sleep 更准确!

Edit 2: The above works for me and now allows me to break the wait when escape is pressed. I have noticed the delay is more accurate than using Thread.Sleep too!

推荐答案

第一个示例是使用 Timer、ManuelResetEvent 和 Global Keyboard 钩子:

First sample is using Timer, ManuelResetEvent and Global Keyboard hook:

我没有包含键盘钩子代码,因为它太大了.您可以在此处找到它.

I did not include keyboard hook code because it's too large. You can find it 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().第一个示例只是给您一个想法.

When you hook to keyboard and ESC is pressed, simply call: _signal.Set(). This first sample is just to give you an idea.

第二个样本:

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

第一个示例更可靠,因为键盘钩子使用回调来通知按下了哪个键.第二个示例的工作方式类似于拉动",但并非每次按键都会被收集.

First sample is more reliable as keyboard hook use callback to inform which key was pressed. Second sample works like 'Pull' and it can happen not every key press will be collected.

这篇关于如何将程序延迟一定的毫秒数,或直到按下某个键?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆