サードパーティ アプリケーション用のマルチスレッド dll があります。私の dll は、カスタム メッセージ タイプで SendMessage を呼び出すことにより、メイン UI スレッドにメッセージを呼び出します。
typedef void (*CallbackFunctionType)();
DWORD _wm;
HANDLE _hwnd;
DWORD threadId;
Initialize()
{
_wm = RegisterWindowMessage("MyInvokeMessage");
WNDCLASS wndclass = {0};
wndclass.hInstance = (HINSTANCE)&__ImageBase;
wndclass.lpfnWndProc = wndProcedure;
wndclass.lpszClassName = "MessageOnlyWindow";
RegisterClass(&wndclass);
_hwnd = CreateWindow(
"MessageOnlyWindow",
NULL,
NULL,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
(HINSTANCE)&__ImageBase,
NULL);
threadId = GetCurrentThreadId();
}
void InvokeSync(CallbackFunctionType funcPtr)
{
if (_hwnd != NULL && threadId != GetCurrentThreadId())
SendMessage(_hwnd, _wm, 0, (LPARAM)funcPtr);
else
funcPtr();
}
static LRESULT CALLBACK wndProcedure(
HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if (Msg == _wm)
{
CallbackFunctionType funcPtr = (CallbackFunctionType)lParam;
(*funcPtr)();
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
アプリケーションは MDI で、ドキュメントを開く/コンテンツを抽出する/バックグラウンドで処理する/大量のドキュメントを保存するため、常にアクティブなドキュメントを切り替えたり、新しいドキュメントを開いたり閉じたりしています。
私の問題は、上記の InvokeSync() 関数を使用してメイン スレッドにメッセージを呼び出そうとすると、処理が停止することがあることです。
デバッガーで一時停止すると、メイン スレッドに次のコール スタックがあることがわかります。
user32.dll!_NtUserGetMessage@16() + 0x15 bytes
user32.dll!_NtUserGetMessage@16() + 0x15 bytes
mfc42.dll!CWinThread::PumpMessage() + 0x16 bytes
// the rest is normal application stuff
ロックされているバックグラウンド スレッドには、次のような呼び出し履歴があります。
user32.dll!_NtUserMessageCall@28() + 0x15 bytes
user32.dll!_NtUserMessageCall@28() + 0x15 bytes
mydll!InvokeSync(funcPtr)
// the rest is expected dll stuff
そのため、「SendMessage()」呼び出しでスタックしているように見えますが、私が見る限り、メイン スレッドのメッセージ ポンプはアイドル状態になっています。
ただし、非アクティブなドキュメントを (アクティブにするために) 手動でクリックすると、どういうわけかすべてが起動し、SendMessage() イベントが最終的に通過し、処理が再開されます。
メイン アプリケーションは、ドキュメントごとに 1 ファイバーの Microsoft ファイバーを使用します。SendMessage がバックグラウンド ファイバーでスタックして、スイッチ アウトされたりすることはありますか? 非アクティブまたは何かになる直前のファイバーで、コンテキストスイッチを強制することによってのみ、そのファイバーはメッセージを処理することができますか? 糸と繊維の相互作用がよくわからないので、ストローをつかんでいます。
メッセージがこのように未処理のまま放置される原因は何ですか? さらに重要なことに、この状況が発生するのを防ぐ方法はありますか? または、少なくとも、そのような状況をどのようにデバッグしますか?