現在、マネージ C++ で winsock サーバー側ソケットを作成しています。LPWSAOVERLAPPED オブジェクトを作成して WSASend 関数に渡した後、操作が非ブロック化を完了したときに削除する場所がわかりません (WSASend は SOCKET_ERROR を返し、WSAGetLastError() は WSA_IO_PENDING を返します)。私の現在の解決策は、System::Threading::WaitHandle を作成し、待機ハンドルへの安全でないポインターを取得し、それを LPWSAOVERLAPPED オブジェクトの下の hEvent に渡すことでした。ただし、送信操作がいつ完了するかはあまり気にしないため、これは不要なオブジェクトの作成を引き起こしています。一方、操作を完全にノンブロッキングにするためには、LPWSAOVERLAPPED オブジェクトが必要です。これを解決するためのより良い解決策はありますか? これが私の現在のコードです:
void Connectivity::ConnectionInformation::SendData(unsigned char data[], const int length)
{
if (isClosed || sendError)
return;
Monitor::Enter(this->sendSyncRoot);
try
{
LPWSAOVERLAPPED overlapped = OverlappedObjectPool::GetOverlapped();
WaitHandle ^ handle = gcnew ManualResetEvent(false);
IntPtr handlePointer = handle->SafeWaitHandle->DangerousGetHandle();
sendInfo->buf = (char*)data;
sendInfo->len = length;
overlapped->Internal = 0;
overlapped->InternalHigh = 0;
overlapped->Offset = 0;
overlapped->OffsetHigh = 0;
overlapped->Pointer = 0;
overlapped->hEvent = (void*)handlePointer; //Set pointer
if (WSASend(connection, sendInfo, 1, NULL, 0, overlapped, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() == WSA_IO_PENDING)
{
ThreadPool::UnsafeRegisterWaitForSingleObject(handle, sentCallback, (IntPtr)((void*)overlapped), -1, true);
}
else
{
this->sendError = true;
//The send error bool makes sure that the close function doesn't get called
//during packet processing which could lead to a lot of null reffernce exceptions.
OverlappedObjectPool::GiveObject(overlapped);
}
}
else
{
handle->Close();
sentData((IntPtr)((void*)overlapped), false);
}
}
finally
{
Monitor::Exit(this->sendSyncRoot);
}
}