C++ 睡眠时检查输入

C++ 睡眠时检查输入,c++,c++11,visual-studio-2015,c++14,C++,C++11,Visual Studio 2015,C++14,两个功能:CheckInput和SendKey 检查输入检查是否按下Alt-J。按下Alt-J时,切换布尔值,允许SendKey每隔500毫秒发送一次Enter键 我需要CheckInput仍然能够获得用户输入并更改bool,从而停止发送enter,同时SendKey仍在睡眠中等待,否则现在我必须按住Alt-J直到下一个500毫秒结束 有什么办法吗?它看起来很简单,但我却无法控制它 (基本上,脚本每500毫秒按一次enter键,无需等待500毫秒即可打开和关闭) 正如评论员提到的,您需要将循环放

两个功能:CheckInput和SendKey

检查输入检查是否按下Alt-J。按下Alt-J时,切换布尔值,允许SendKey每隔500毫秒发送一次Enter键

我需要CheckInput仍然能够获得用户输入并更改bool,从而停止发送enter,同时SendKey仍在睡眠中等待,否则现在我必须按住Alt-J直到下一个500毫秒结束

有什么办法吗?它看起来很简单,但我却无法控制它

(基本上,脚本每500毫秒按一次enter键,无需等待500毫秒即可打开和关闭)


正如评论员提到的,您需要将循环放入线程中,如本例所示:

atomic_int  temp;

std::thread t( [&temp]()
              {

                  while( temp!= -1){
                      std::this_thread::sleep_for(std::chrono::milliseconds(500));
                      temp=0;
                  }
              });
您可以使用一个条件变量并有一个线程来等待它


第二个线程(或主循环)将在循环中等待键盘输入,并在输入到达后向条件变量发送信号。

如果可以使用Windows事件循环,这将更加平滑

如果你不能,你应该模拟它

创建可以存储事件信息的线程安全队列。您需要两种类型的事件-击键和计时器计时

一个线程将休眠500毫秒,并以循环的形式发送计时器滴答事件。另一个线程将调用Console.ReadKey,并发送一个击键事件——也是在一个循环中


您的主线程将等待事件从队列中到达并处理它们。

我想只需检查自上次按下Enter键以来的时间是否超过500毫秒,以便它在系统时间之外工作。不幸的是,我还没有找到同时运行两个进程的方法,但这似乎是我所需要的:

void SendKey() {
    if (Active){
        keybd_event(0x0D, 0x0A, 0, 0);
        Sleep(16);
        keybd_event(0x0D, 0X0A, KEYEVENTF_KEYUP, 0);
    }
}

void CheckInput() {
    auto t1 = Clock::now() + chrono::seconds(1);
    int temp = 0;
    while (temp == 0) {
        if ((GetKeyState(0x12) & 0x8000) && (GetKeyState(0x4A) & 0x8000)) {
            Active = !Active;
        }
        if (Clock::now() > t1) {
            SendKey();
            temp = 1;
        }
    }
}

int main()
{
    while (1) {
        thread t1(CheckInput);
        t1.join();
    }
    return 0;
}

这基本上存储了运行CheckInput的时间,并设置了一个设定的目标,即未来1秒。然后,它将继续检查输入,还将检查时间是否已过设定的目标,当时间已过时,它将调用SendKey,然后再次重复。

无论采用何种解决方案,都应该在线程中设置循环,而不是在主函数中。两个线程都应该有自己的循环。您可以在主线程上进行主处理;您只需要在一个单独的线程上进行标志管理。我不希望任何线程互相等待。例如,我希望CheckInput和SendKey同时运行,就好像它们是两个独立线程上运行的while循环,彼此独立,因此如果一个线程休眠,另一个线程仍然可以继续检查输入。是的,有一些退出条件。通过使用原子变量避免数据竞争。等待一个条件变量来按键可以避免两个线程而不是一个线程旋转。我已经尝试将循环移动到实际函数,但是睡眠(500)在SendKeys内部,整个程序仍然需要等待它,所以我仍然需要等待500毫秒,然后才能注册CheckInput的输入让SendKeys等待一个条件变量,这样你可以立即唤醒线程,这里有一个很好的例子:就像我说的,不是线程唤醒得太晚,事实上,通过在SendKeys中休眠,CheckInput也被阻止,但是我需要SendKeys中的延迟,因为我只希望它每500毫秒运行一次,如果我在程序中的任何地方设置500毫秒的延迟,那么一切都必须等待。同样的事情也适用于条件变量,因为我仍然希望两个函数都继续运行,而不必等待另一个。这基本上是我想要做的,但我不知道如何使一个线程睡眠500毫秒,同时仍然允许另一个线程继续。这就像我使用多线程的方式一样,当我真的需要并行时,它仍然像一个线程一样按顺序运行。启动两个线程。其中一个会睡觉,另一个不会。这就是线程的意义所在。将didiz的答案作为解决方案,因为他帮助最多,并提醒了我chrono::毫秒,但出于我的需要,这是可行的。循环仍在每次运行时创建和销毁线程,这是有意的吗?
void SendKey() {
    if (Active){
        keybd_event(0x0D, 0x0A, 0, 0);
        Sleep(16);
        keybd_event(0x0D, 0X0A, KEYEVENTF_KEYUP, 0);
    }
}

void CheckInput() {
    auto t1 = Clock::now() + chrono::seconds(1);
    int temp = 0;
    while (temp == 0) {
        if ((GetKeyState(0x12) & 0x8000) && (GetKeyState(0x4A) & 0x8000)) {
            Active = !Active;
        }
        if (Clock::now() > t1) {
            SendKey();
            temp = 1;
        }
    }
}

int main()
{
    while (1) {
        thread t1(CheckInput);
        t1.join();
    }
    return 0;
}