如何在c / c ++中停止来自另一个线程的主线程

时间:2016-12-09 08:05:22

标签: c++ multithreading winapi

如果捕获VK_ESCAPE键,我想从另一个线程停止主线程,并在用户按任意键时恢复主线程。 我打算构造“ThreadProc1”线程来捕获按下的键:

DWORD WINAPI ThreadProc1(LPVOID param){
    while(1){
        if(GetAsyncKeyState(VK_ESCAPE)){
            //Stop the main thread
        }
    }
}

2 个答案:

答案 0 :(得分:1)

不要那样做。要么:1)当主线程从Esc键接收到消息时再次按下该消息,直到再次按下该消息时,使主线程跳过所有有意义的动作。 2)使用CreateEvent并在其上放置主线程WaitForMultipleObjects,然后从其他线程使用SetEvent唤醒它,或者在超时时将其唤醒。

主线程如果启动消息泵,则是Windows应用程序的“心脏和大脑”,停止它相当于临床死亡。可以返回的“阻塞”动作,如从文件,套接字等中读取,是合法的,其他线程不会因死锁而导致。睡觉是合法的,因为线程可以被唤醒。将消息泵线程置于睡眠状态而不替代消息泵是可疑的行为,这种应用可能被认为是“挂起”。停止的驱动程序将被杀死,服务无限期挂起,桌面GUI将提供用户停止应用程序(或将在企业环境中停止该应用程序,如果管理员是偏执的),并将在任务栏中标记它“没有响应“等等。

答案 1 :(得分:1)

正式暂停线程非常简单 - SuspendThread然后ResumeThread - 但是:

  

此功能主要供调试器使用。它不是   旨在用于线程同步。调用SuspendThread   在拥有同步对象的线程上,例如互斥锁或   临界区,如果调用线程尝试,可能导致死锁   获取被挂起的线程拥有的同步对象。至   避免这种情况,应用程序中的一个线程不是   调试器应该通知另一个线程暂停自己。目标   线程必须设计为观察此信号并做出响应   适当。

很可能在挂起时由线程调用(HeapAllocHeapFree(并且它经常在Windows消息处理上调用)。和线程保持堆临界区。如果在此之后工作线程也直接或间接(非常高的可能性)调用HeapAlloc(或同一堆的任何其他堆函数 - 通常这是主进程堆) - 你遇到了死锁。

你当然可以说发送一些带有事件句柄的已知消息给主线程 - 主线程将等待事件,直到工作线程没有调用SetEvent - 但这也是坏的而不是质量解决方案。

UI线程一定不能阻塞等待,永久等待Windows消息。我不知道您尝试执行哪项任务,但100%确定现有解决方案,而不会阻止UI线程