【问题标题】:How to stop main thread from another thread in c/c++如何在 C/C++ 中从另一个线程停止主线程
【发布时间】:2016-12-09 08:05:22
【问题描述】:

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

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

【问题讨论】:

  • 你的意思是你想杀死线程,还是只是suspend它?
  • 另外,我认为你的设计有点落后。通常你会产生线程来执行其他工作,而主线程继续处理主要事件(比如检查键盘按下)。
  • 由于您使用的是Windows API,建议您查看the list of process and thread functions。我相信你可以在那里找到一些东西。
  • @Some程序员老兄>另外,我认为你的设计有点倒退。
  • 您需要退后一步,尝试正确理解线程和输入的工作原理

标签: c++ multithreading winapi


【解决方案1】:

正式挂起线程很容易 - SuspendThread 然后ResumeThread - 但是:

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

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

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

UI 线程根本不能做阻塞等待,永久等待 Windows 消息。我不完全知道您尝试执行哪个任务,但 100% 确定存在完全不阻塞 UI 线程的解决方案

【讨论】:

    【解决方案2】:

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

    主线程如果启动了消息泵,是Windows应用程序的“心脏和大脑”,停止它就等于临床死亡。可以返回的“阻塞”操作,例如从文件读取,套接字等是合法的,前提是其他线程不会因死锁而导致。休眠是合法的,因为线程可以被唤醒。在不替代消息泵的情况下让消息泵线程进入睡眠状态是一种可疑的行为,这样的应用程序可能被认为是“挂起”。以这种方式停止的驱动程序将被终止,服务无限期挂起,桌面 GUI 将让用户停止应用程序(或者将在企业环境中停止该应用程序,如果管理员是偏执的),并会在任务栏中将其标记为“无响应"等。

    【讨论】:

    • Windows 应用程序没有“主线程” 的概念。有一个“主线程”,但这只是普通线程,唯一的不同之处在于,它是进程中创建的第一个线程。阻塞主线程没有负面影响(除非该线程拥有 GUI)。 WaitForSingleObject 确实 阻塞,虽然从 GUI 线程调用它是合法的,但它会导致 GUI 挂起。 MsgWaitForMultipleObjects 是一个更好的选择(即使使用起来很棘手)。
    • 概率 > 0.999 创建的第一个线程是 GUI 线程
    • @DavidHeffernan:软件开发不是统计学的练习。此外,99.9% 的统计数据都是凭空捏造的。
    • @iinspectable 我已经纠正了,有脑子,是的,我的意思是多个对象等待。如果 OP 不是用 API 编写整个应用程序的人之一,那么他的 GUI 就在主线程中。在我的语言中,主要和主要是同一个词,当我已经知道英语时,我没有使用裸 API。大多数框架在主线程中初始化消息泵。实际上,不一定应该是 GUI,例如服务有自己的消息泵,但他们不访问 GUI。一切都是关于回应与否。如果是驱动程序,Windows 会自动杀死并重新启动那些停止响应一段时间的驱动程序。
    • @IInspectable 我指出,假设主线程是 UI 线程通常是非常实用的。如果不是,那就这样吧。但通常是这样。就是这样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-22
    • 1970-01-01
    • 1970-01-01
    • 2017-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多