DCOM pingシステムについてはよくわかりませんが、1つのオプションは、通知を別のスレッドプールに単純にファームオフすることです。これは、ブロックしているクライアントの数が少ない場合の影響を軽減するのに役立ちます。もちろん、クライアントが多すぎると問題が発生し始めます。
これを行う簡単な方法は、を使用することです。これQueueUserWorkItem
により、アプリケーションのシステムスレッドプールで渡されたコールバックが呼び出されます。MTAを使用していると仮定すると、これがあなたがする必要があるすべてです:
static InfoStruct {
IRemoteHost *pRemote;
BSTR someData;
};
static DWORD WINAPI InvokeClientAsync(LPVOID lpInfo) {
CoInitializeEx(COINIT_MULTITHREADED);
InfoStruct *is = (InfoStruct *)lpInfo;
is->pRemote->notify(someData);
is->pRemote->Release();
SysFreeString(is->someData);
delete is;
CoUninitialize();
return 0;
}
void InvokeClient(IRemoteHost *pRemote, BSTR someData) {
InfoStruct *is = new InfoStruct;
is->pRemote = pRemote;
pRemote->AddRef();
is->someData = SysAllocString(someData);
QueueUserWorkItem(InvokeClientAsync, (LPVOID)is, WT_EXECUTELONGFUNCTION);
}
メインスレッドがSTAにある場合、これは少しだけ複雑になります。アパート間でインターフェイスポインタを使用CoMarshalInterThreadInterfaceInStream
して渡す必要があります。CoGetInterfaceAndReleaseStream
static InfoStruct {
IStream *pMarshalledRemote;
BSTR someData;
};
static DWORD WINAPI InvokeClientAsync(LPVOID lpInfo) {
CoInitializeEx(COINIT_MULTITHREADED); // can be STA as well
InfoStruct *is = (InfoStruct *)lpInfo;
IRemoteHost *pRemote;
CoGetInterfaceAndReleaseStream(is->pMarshalledRemote, __uuidof(IRemoteHost), (LPVOID *)&pRemote);
pRemote->notify(someData);
pRemote->Release();
SysFreeString(is->someData);
delete is;
CoUninitialize();
return 0;
}
void InvokeClient(IRemoteHost *pRemote, BSTR someData) {
InfoStruct *is = new InfoStruct;
CoMarshalInterThreadInterfaceInStream(__uuidof(IRemoteHost), pRemote, &is->pMarshalledRemote);
is->someData = SysAllocString(someData);
QueueUserWorkItem(InvokeClientAsync, (LPVOID)is, WT_EXECUTELONGFUNCTION);
}
わかりやすくするためにエラーチェックが省略されていることに注意してください。もちろん、すべての呼び出しをエラーチェックする必要があります。特に、RPC_S_SERVER_UNAVAILABLE
その他のネットワークエラーをチェックし、問題のあるクライアントを削除する必要があります。
検討したいいくつかのより洗練されたバリエーションには、クライアントごとに一度に1つの要求のみが処理中であることを確認し(したがって、スタックしたクライアントの影響をさらに減らす)、マーシャリングされたインターフェイスポインターをMTAにキャッシュする(メインスレッドがSTA)-CoMarshalInterThreadInterfaceInStream
ネットワークリクエストを実行する可能性があるため、メインスレッドでブロックされるリスクを冒すのではなく、クライアントが接続されていることがわかっている場合は、事前に処理するのが理想的です。