Реализация обратного вызова с использованием цикла сообщений Windows - PullRequest
2 голосов
/ 28 декабря 2011

У меня есть библиотека C ++ ( Win32 Console), где я реализовал асинхронную функцию с использованием таймера. Асинхронный метод возвращает информацию об устройстве.

Я создал отдельный поток, «Поток таймера», для создания скрытого окна, а затем я вызываю SetTimer() и затем реализованный цикл обработки сообщений.

Когда таймер истекает, он активирует обратный вызов.

Когда я использую библиотеку в консольном приложении, она работает нормально.

В приложении MFC я делаю почтовое сообщение, чтобы обновить пользовательский интерфейс при срабатывании обратного вызова. Сообщение не работает.

Если я удаляю цикл сообщений в библиотеке, он прекрасно работает в приложении MFC.

Я пришел к выводу, что:

Я полагаю, что проблема связана с двумя циклами сообщений, одним MFC (основной поток) и циклом сообщений TimerThread. Таким образом, когда вызывается обратный вызов и последующее PostMessage приводит к циклу сообщений TimerThread и не сообщается в цикле сообщений MFC (основной поток).

Если я удаляю цикл сообщений TimerThread, он отлично работает в приложении MFC, но не работает в консольном приложении.

Как мне преодолеть эту проблему?

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
}

В приложении MFC / console я реализую IDeviceEnumerationCallback для получения обратного вызова.

Я использую Bonjour API для перечисления устройства, и все методы в Bonjour API являются обратными вызовами.

Я ожидаю некоторого интервала времени для перечисления устройства с использованием Bonjour API, а затем через 400 мс я звоню в функцию обратного вызова для возврата результата. В приложении MFC при вызове обратного вызова я делаю PostMessage() для обновления пользовательского интерфейса.

Раньше я пробовал без Windows сообщение сообщений. У меня была функция SetTimer, и она работает с приложением MFC, но для консольного приложения обратный вызов никогда не вызывается, поэтому я реализовал здесь обработчик сообщений. Теперь это не работает для приложения MFC.

Ответы [ 2 ]

0 голосов
/ 28 декабря 2011

Во-первых, нет причин делать то, что вы делали: создавая отдельные потоки, затем создавая в нем окно, устанавливая таймер окна, запуская цикл обработки сообщений, отвечая на сообщение WM_TIMER и вызывая обратный вызов.

Если вы создаете «свою» ветку - вам все это не нужно.Вы можете просто реализовать простой цикл с помощью либо Sleep (или WaitForXXXX, если вы хотите отключить опцию), и вызвать свой обратный вызов.

Обычно создается скрытое окно с таймером, чтобы избегать создание дополнительной темы.То есть внутри потока, который работает с графическим интерфейсом (и, следовательно, запускает цикл сообщений), вы создаете окно, и оно будет обслуживаться циклом сообщений.На самом деле это то, что вы могли бы сделать в своем приложении MFC.

Однако, как вы сказали, вам нужен общий код как для MFC, так и для консольных приложений.

В приложении MFC яотправка сообщения для обновления пользовательского интерфейса при срабатывании обратного вызова. сообщение не работает.

Что именно вы подразумеваете под «отправленным сообщением»?Сообщение должно быть отправлено либо в конкретное окно, либо в ветку.В первом случае она отправляется в оконную процедуру, а во втором случае за обработку сообщения отвечает реализация цикла сообщений.

Если вы публикуете свое сообщение в определенном окне - как вы получаете его дескриптор (HWND)?Это главное окно вашего приложения (AfxGetMainWnd)?Что начинает работать твой поток после того, как MFC создал главное окно, или раньше?

Я задаю все эти вопросы, потому что ты, похоже, новичок (без обид), и это типичные ошибки.

0 голосов
/ 28 декабря 2011

Проблема в том, что вам не следует создавать скрытое окно и использовать 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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...