Я использовал примеры из MSDN и (в основном) CodeProject для написания сокет-сервера.Я пытаюсь осмыслить потокобезопасность кода.Все события сокета инициируют метод IO_Completed, который проверяет SAEA на предмет последнего типа операции (отправка или получение):
void IO_Completed(object sender, SocketAsyncEventArgs e)
{
// determine which type of operation just completed and call the associated handler
switch (e.LastOperation)
{
case SocketAsyncOperation.Receive:
ProcessReceive(e);
break;
case SocketAsyncOperation.Send:
ProcessSend(e);
break;
default:
throw new ArgumentException("The last operation completed on the socket was not a receive or send");
}
}
Принимая во внимание входящие вызовы, нужно ли ProcessReceive () быть полностью поточно-ориентированным, поскольку этовызывается много раз за короткий промежуток времени, если клиентов много, или он как-то блокируется, чтобы полностью завершиться до следующего вызова этого события?Я делаю больше, чем просто возвращаю полученное сообщение обратно клиенту (что и делают примеры).
Даже в примерах ProcessReceive () является довольно длинным методом (см. Ниже) и, безусловно, долженбыть под угрозой коррупции из второго потока.К тому времени, когда я добавляю код, мне нужно сделать что-то осмысленное (вызвать службу WCF), вероятность повторного запуска того же кода должна быть очень высокой.
Что мне нужно сделать, чтобы сделать ProcessReceive ()(и другие связанные методы), как правило, потокобезопасны без ущерба для производительности, получаемой от использования SocketAsyncEventArgs?
Пример метода ProcessReceive () ниже:
private void ProcessReceive(SocketAsyncEventArgs receiveSendEventArgs)
{
DataHoldingUserToken receiveSendToken =
(DataHoldingUserToken)receiveSendEventArgs.UserToken;
if (receiveSendEventArgs.SocketError != SocketError.Success)
{
receiveSendToken.Reset();
CloseClientSocket(receiveSendEventArgs);
return;
}
if (receiveSendEventArgs.BytesTransferred == 0)
{
receiveSendToken.Reset();
CloseClientSocket(receiveSendEventArgs);
return;
}
Int32 remainingBytesToProcess = receiveSendEventArgs.BytesTransferred;
if (receiveSendToken.receivedPrefixBytesDoneCount <
this.socketListenerSettings.ReceivePrefixLength)
{
remainingBytesToProcess = prefixHandler.HandlePrefix(receiveSendEventArgs,
receiveSendToken, remainingBytesToProcess);
if (remainingBytesToProcess == 0)
{
StartReceive(receiveSendEventArgs);
return;
}
}
bool incomingTcpMessageIsReady = messageHandler
.HandleMessage(receiveSendEventArgs,
receiveSendToken, remainingBytesToProcess);
if (incomingTcpMessageIsReady == true)
{
receiveSendToken.theMediator.HandleData(receiveSendToken.theDataHolder);
receiveSendToken.CreateNewDataHolder();
receiveSendToken.Reset();
receiveSendToken.theMediator.PrepareOutgoingData();
StartSend(receiveSendToken.theMediator.GiveBack());
}
else
{
receiveSendToken.receiveMessageOffset = receiveSendToken.bufferOffsetReceive;
receiveSendToken.recPrefixBytesDoneThisOp = 0;
StartReceive(receiveSendEventArgs);
}
}