简体   繁体   English

使用Windows消息循环的回调实现

[英]Callback implementation using Windows message loop

I have C++ library ( Win32 Console) where I have implemented an asynchronous function using a timer. 我有C ++库( Win32控制台),在其中使用计时器实现了异步功能。 The asynchronous method returns device information. 异步方法返回设备信息。

I have created a separate thread, "Timer Thread", to create a hidden window and then I call SetTimer() and then the implemented message loop. 我创建了一个单独的线程“ Timer Thread”以创建一个隐藏的窗口,然后调用SetTimer() ,然后调用已实现的消息循环。

When the timer expires, it enables a callback. 计时器到期时,它将启用回调。

When I use the library in a console application, it is working fine. 当我在控制台应用程序中使用该库时,它运行良好。

In an MFC application I am doing a post message to update the user interface when the callback triggers. MFC应用程序中,我正在执行发布消息,以在回调触发时更新用户界面。 The post message is not working. 帖子消息不起作用。

If I remove the message loop in the library, it is working fine in the MFC application. 如果我删除了库中的消息循环,则它在MFC应用程序中工作正常。

I came to conclusion that: 我得出的结论是:

I guess the problem is due to two message loops, one MFC (main thread) and the TimerThread message loop. 我猜问题是由于两个消息循环,一个MFC(主线程)和TimerThread消息循环。 So when the callback is called and the subsequent PostMessage results in the TimerThread message loop and not reported in the MFC (main thread) message loop. 因此,当回调被调用并且后续的PostMessage导致TimerThread消息循环,而在MFC(主线程)消息循环中未报告。

If I remove the TimerThread message loop then it works fine in the MFC application, but it fails to work in the console application. 如果我删除了TimerThread消息循环,则它在MFC应用程序中可以正常工作,但在控制台应用程序中则无法工作。

How do I overcome this problem? 我该如何克服这个问题?

class IDeviceEnumerationCallback
{
     public:
         virtual void onDeviceDiscovered(DeviceInfo* pDeviceInfo,unsigned short nNoOfDevice) = 0;
};

class IDeviceDiscovery
{
    public:
        virtual int InitialiseDiscovery(IDeviceEnumerationCallback*) = 0;

        virtual void UnInitialiseDiscovery() = 0;

        virtual int EnumerateDevice() = 0;
};

class CDeviceDiscovery:IDeviceDiscovery
{
    //Implementation
}

In the MFC/console application I am implementing IDeviceEnumerationCallback to get a callback. 在MFC /控制台应用程序中,我正在实现IDeviceEnumerationCallback以获取回调。

I am using Bonjour API to enumerate the device and all the methods in Bonjour API are callbacks. 我正在使用Bonjour API枚举设备,并且Bonjour API中的所有方法都是回调。

I am wating for some time interval to enumerate a device using Bonjour API and then say after 400 ms I am calling a callback to return the result. 我想在一段时间内使用Bonjour API枚举设备,然后说400毫秒后我正在调用回调以返回结果。 In the MFC application when the callback is called, I am doing a PostMessage() to update the user interface. 在MFC应用程序中,当调用回调时,我正在执行PostMessage()以更新用户界面。

Earlier I tried without Windows message pump. 之前,我尝试不使用Windows消息泵。 I had a SetTimer function, and it is working with the MFC application, but for the console application, the callback never gets called, so I implemented a message pump here. 我有一个SetTimer函数,它可以与MFC应用程序一起使用,但是对于控制台应用程序,从未调用过回调,因此我在这里实现了消息泵。 Now it is not working for MFC application. 现在,它不适用于MFC应用程序。

The problem is that you should not be creating a hidden window and using SetTimer instead you should be using the MFC worker thread functionality for background work. 问题是您不应该创建一个隐藏的窗口,而应该使用SetTimer而应该使用MFC工作线程功能进行后台工作。

//You create a thread  like so.
// you need a CMyObject only if you need to pass any information
//to the thread function.
CMyObject *pNewObject = new CMyObject;
AfxBeginThread(MyThreadProc, pNewObject);


//This function will be run in separate thread
UINT MyThreadProc( LPVOID pParam )
{
    //The parameter that was passed to this function
    CMyObject* pObject = (CMyObject*)pParam;

    while( 1 )
    {
        //add your code to do stuff.

        Sleep(5000); //or whatever your SetTimer interval was 
    }

    return 0;   // thread completed successfully
}

First, there's no reason to do what you did: creating a separate threads, then creating a window in it, set the window timer, run the message loop, respond to the WM_TIMER message and invoke the callback. 首先,没有理由做您要做的事情:创建一个单独的线程,然后在其中创建一个窗口,设置窗口计时器,运行消息循环,响应WM_TIMER消息并调用回调。

If you create "your own" thread - you don't actually need all this. 如果创建“自己的”线程-实际上并不需要所有这些。 You could just implement a simple loop with either Sleep (or WaitForXXXX if you want an abort option), and invoke your callback. 您可以使用Sleep (或者如果需要中止选项,则使用WaitForXXXX来实现一个简单的循环,然后调用您的回调。

Usually one creates a hidden window with a timer to avoid creating an additional thread. 通常,一个带有计时器的隐藏窗口可避免创建其他线程。 That is, within a thread that operates GUI (and hence - runs the message loop) you create a window, and it will be served by the message loop. 也就是说,在操作GUI(并因此运行消息循环)的线程中,您创建了一个窗口,该窗口将由消息循环提供服务。 Actually this is would you could do in your MFC app. 实际上,这是您可以在MFC应用程序中执行的操作。

However, as you said, you want a generic code for both MFC and console apps. 但是,正如您所说的,您需要同时为MFC和控制台应用程序提供通用代码。

In MFC application I am doing post message to update UI when the callback triggers.the post message is Not wokring. 在MFC应用程序中,我正在执行回调触发时更新UI的发布消息。发布消息未唤醒。

What exactly do you mean by "diung post message"? “ diung post message”到底是什么意思? The message should be posted either to a specific window, or to the thread. 该消息应发布到特定窗口或线程中。 In the first case it's dispatched to the window procedure, and in the second case the message loop implementation is responsible for handling the message. 在第一种情况下,它被分派到窗口过程,在第二种情况下,消息循环实现负责处理消息。

If you post your message to a specific window - how do you get its handle ( HWND )? 如果将消息发布到特定窗口-如何获得其句柄( HWND )? Is it your app's main window ( AfxGetMainWnd )? 它是您应用程序的主窗口( AfxGetMainWnd )吗? What does your thread start working, after the MFC has created the main window, or earlier? 在MFC创建主窗口或更早之后,您的线程开始工作吗?

I ask all those question because you seem to be a newbie (no offences), and those are typical mistakes. 我问所有这些问题,因为您似乎是新手(无犯罪),而这些都是典型的错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM