2
votes

I have C++ library (Win32 Console) where I have implemented an asynchronous function using a timer. 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.

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. The post message is not working.

If I remove the message loop in the library, it is working fine in the MFC application.

I came to conclusion that:

I guess the problem is due to two message loops, one MFC (main thread) and the TimerThread message loop. 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.

If I remove the TimerThread message loop then it works fine in the MFC application, but it fails to work in the console application.

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.

I am using Bonjour API to enumerate the device and all the methods in Bonjour API are callbacks.

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. In the MFC application when the callback is called, I am doing a PostMessage() to update the user interface.

Earlier I tried without Windows message pump. 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. Now it is not working for MFC application.

2
Posting a message from one thread to a window managed by another thread/message loop should be fine. The WindowProc should get called with the message OK, assuming the handle is correct. What does the PostMessage() return?Martin James
SetTimer is known to be notoriously twisted and error prone. Messages are not posted, but created only when you call GetMessage, but not when there are already high priority messages in the queue (no joke!). Use a waitable timer.Damon

2 Answers

0
votes

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.

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.

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. Actually this is would you could do in your MFC app.

However, as you said, you want a generic code for both MFC and console apps.

In MFC application I am doing post message to update UI when the callback triggers.the post message is Not wokring.

What exactly do you mean by "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)? Is it your app's main window (AfxGetMainWnd)? What does your thread start working, after the MFC has created the main window, or earlier?

I ask all those question because you seem to be a newbie (no offences), and those are typical mistakes.

0
votes

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.

//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
}