У меня есть приложение без окон, единственной целью которого является установка 32-битного DLL-файла ловушки и ожидание выхода из родительской программы (64-битной программы). 64-разрядная программа написана на C#, а безоконное приложение — на C++. Первоначально у меня был этот цикл GetMessage, который удерживал программу открытой:
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Я закрывал приложение C++ с помощью метода Process.Kill в C#, но обнаружил, что это не позволяет корректно закрыть приложение C++. Кроме того, в случае сбоя приложения C# приложение C++ останется открытым навсегда. Я проверил приложение С++, чтобы убедиться, что приложение С# все еще работает, используя этот цикл:
while(true)
{
if(PeekMessage(&msg, NULL, 0, 0, true))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(!isMainProgramRunning())
break;
Sleep(1000);
}
По какой-то причине Сон вызывает проблемы. Перехватчики, установленные файлом DLL, — это WH_CBT и WH_KEYBOARD. Всякий раз, когда я нажимаю клавишу, пока приложение C++ работает с этим циклом, клавиши просто съедаются. Удаление спящего режима заставляет его работать нормально, но, как и ожидалось, он использует 100% CPU, что я не хочу. Я попытался полностью удалить цикл сообщений и вместо этого использовать WaitForSingleObject с бесконечным тайм-аутом в потоке, который завершится, когда isMainProgramRunning вернет false. Это в основном блокирует весь компьютер.
Я действительно не понимаю, почему GetMessage, который, насколько я видел, никогда не возвращался, но приостанавливал основной поток на неопределенный срок, не вызывал этих проблем, а WaitForSingleObject заставляет каждое приложение зависать, когда я нажимаю на него. Как я могу заставить приложение С++ оставаться открытым, пока приложение С# не закроется?
Редактировать:
Поскольку мне было указано, что сон в насосе сообщений — это плохо, позвольте мне задать следующий вопрос: есть ли способ указать тайм-аут для ожидания сообщения, чтобы программа не ждала сообщения бесконечно долго, а, скорее, подождите около 250 мс, тайм-аут, позвольте мне запустить метод isMainProgramRunning, затем подождать еще немного?
Редактировать2:
Я попытался использовать MsgWaitForMultipleObjects, хотя и несколько иначе, чем предложил Лео. Это цикл, который я использовал:
while(MsgWaitForMultipleObjects (0, NULL, true, 250, QS_ALLPOSTMESSAGE) != WAIT_FAILED)
{
if(PeekMessage(&msg, NULL, 0, 0, true))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(!isMainProgramRunning())
break;
}
Опять у меня была та же проблема со сном. Я также попытался приостановить основной поток и возобновить его другим потоком. Та же проблема. Что делает GetMessage, что позволяет ему ждать, не вызывая этих проблем? Возможно, это должно быть предметом другого поста, но почему, когда приложение C++, устанавливающее хуки, спит или приостанавливается, кажется, что вся обработка в хуках также приостанавливается?
Редактировать3:
Вот метод DLL, который приложение C++ вызывает для установки хуков:
extern "C" __declspec(dllexport) void install()
{
cbtHook = SetWindowsHookEx(WH_CBT, hookWindowEvents, hinst, NULL);
if(cbtHook == NULL)
MessageBox(NULL, "Unable to install CBT hook", "Error!", MB_OK);
keyHook = SetWindowsHookEx(WH_KEYBOARD, LowLevelKeyboardProc, hinst, NULL);
if(keyHook == NULL)
MessageBox(NULL, "Unable to install key hook", "Error!", MB_OK);
}