是否可以在C ++中创建消息循环而不创建窗口

时间:2018-08-21 06:39:18

标签: c++ visual-c++ windows-messages message-loop

我正在使用某些蓝牙库,并且为了进行某些蓝牙回调,必须使用Windows消息循环。但是根据我的要求,我需要创建一个没有任何GUI的普通C ++程序。是否可以创建没有窗口的消息循环?

main(){
    Discovery disc;
    disc.startDiscovery();
}


Discovery::startDiscovery(){
  __hook(&CallBackFromLibrary::OnDiscoveryStarted, &obj, &Discovery::OnDiscoveryStarted);
  __hook(&CallBackFromLibrary::OnDiscoveryComplete, &obj, &Discovery::OnDiscoveryComplete);  
}


apiObject.discoverBluetoothDevices();

在此示例代码中,在调用apiObject.discoverBluetoothDevices()之后,我应该以OnDiscoveryStarted和OnDiscoveryComplete的形式接收回调。

由于他们使用消息循环进行回调,因此我仅在GUI应用程序上获得了回调。库文档说明消息循环是必需的,因此如何使用消息循环来接收回调。

2 个答案:

答案 0 :(得分:3)

是的,有可能-当线程尝试使用消息队列时,Windows会将消息队列与线程相关联。但是,这样做时会出现一些竞争状况。要发布到线程的消息队列中,请使用PostThreadMessage。但是,该线程只有在调用一个函数尝试从消息队列中读取消息时才具有消息队列(即Windows在该线程尝试使用它之前不会为该线程创建消息队列)。

为防止出现竞争状况,通常需要按照以下顺序进行操作:

  1. 创建互斥锁(未签名)
  2. 调用size_t count = std::thread::hardware_concurrency(); for(size_t i=1;i<count;i++) { new std::thread([&count] { boost::fibers::use_scheduling_algorithm<boost::fibers::algo::work_stealing>(count); }); } boost::fibers::use_scheduling_algorithm<boost::fibers::algo::work_stealing>(count); ,将要传递给新线程的互斥锁的句柄传递给它
  3. 让父母等待互斥体
  4. 具有子调用CreateThread(由于队列尚未创建,因此不会产生任何结果,但这会强制创建队列)。
  5. 让孩子发出互斥信号
  6. 现在,父级将继续工作,并且可以使用PeekMessage,在“知识”中确保子级具有消息队列,这样就可以了。

另一种可能性是孩子创建一个窗口,但将其隐藏。这里的明显优势是与期望使用PostThreadMessageSendMessagePostMessage等(而不是特殊的{{1))将消息发布/发送到普通消息队列的代码兼容。 }}。另一个明显的优点是,它避免了上面概述的线程消息队列跳舞。

当您了解它时,Windows“窗口”的主要特征不在显示器上,而是消息队列,并且显示器上显示的只是根据某些特定情况完成的绘制。消息。隐藏的窗口只不过是消息队列而已。

答案 1 :(得分:1)

非GUI线程中的消息循环:

#include "stdafx.h"
#include <Windows.h>
#include <thread>
#include <iostream>
using namespace std;

void ThreadFunction()
{
    MSG msg;
    BOOL result;

    for (;;)
    {
        result = GetMessage(&msg, nullptr, 0, 0);

        if (result <= 0)
        {
            break;
        }

        cout << msg.message << " " << msg.wParam << " " << msg.lParam << endl;

        //TranslateMessage(&msg);
        //DispatchMessage(&msg);
    }
}

int main()
{
    thread t(ThreadFunction);
    HANDLE h = t.native_handle();
    DWORD dw = GetThreadId(h);

    PostThreadMessage(dw, WM_APP + 1, 1, 2);
    PostThreadMessage(dw, WM_APP + 2, 10, 20);
    PostThreadMessage(dw, WM_QUIT, 10, 20);

    t.join();
    return 0;
}