Ответ 1
Здесь вы меняете две вещи: асинхронный стиль (SocketAsyncEventArgs
до Task
/async
) и уровень абстракции (Socket
to NetworkStream
).
Поскольку вам уже удобно работать с Socket
, я рекомендую просто изменить асинхронный стиль и продолжить использование класса Socket
.
Async CTP не дает Socket
любых async
-совместимых методов (это странно, я предполагаю, что они были исключены по ошибке и будут добавлены в .NET 4.5).
Не сложно создать собственный метод расширения ReceiveAsyncTask
(и аналогичные обертки для других операций), если вы используете мою библиотеку AsyncEx:
public static Task<int> ReceiveAsyncTask(this Socket socket,
byte[] buffer, int offset, int size)
{
return AsyncFactory<int>.FromApm(socket.BeginReceive, socket.EndReceive,
buffer, offset, size, SocketFlags.None);
}
Как только вы это сделаете, ваш StartReceive
может быть записан следующим образом:
private async Task StartReceive()
{
try
{
var buffer = new byte[1024];
while (true)
{
var bytesReceived = await socket.ReceiveAsyncTask(buffer, 0, 1024)
.ConfigureAwait(false);
ProcessData(buffer, bytesReceived);
}
}
catch (Exception ex)
{
// Handle errors here
}
}
Теперь, чтобы устранить многие незначительные моменты:
-
await
не порождает новый поток. Я написал асинхронный/ждущий ввод в моем блоге, как и многие другие.async
/await
позволяет concurrency, но это не обязательно означает многопоточность. - Сотни потоков могут быть проблематичными. Сотни задач, однако, не являются проблемой вообще; пул потоков и BCL предназначены для обработки многих и многих задач.
-
async
/await
не является совершенно новой формой асинхронной обработки; это просто более простой способ выразить асинхронную обработку. Он по-прежнему использует IOCP под ним.async
/await
имеет несколько более низкую производительность, чем методы нижнего уровня; его привлекательность - простота написания и составления асинхронных методов. - В очень загруженной системе может наблюдаться повышенное давление газа при переключении на
async
/await
. Стивен Тууб на параллельной команде написал несколько примерных ожиданий сокета, которые могут помочь в решении этой проблемы. (Сначала я рекомендую использовать простой шаблон и использовать только подход с улучшенной производительностью, если вы сочтете это необходимым, но хорошо знать его там, если вам это нужно). - Методы Async должны возвращать
Task
, если вам действительно не нужно возвращатьvoid
.Task
является ожидаемым, поэтому ваш метод является составным (и более легко проверяемым);void
больше похож на "огонь и забыть" . - Вы можете вызвать
ConfigureAwait(false)
, чтобы сообщить остальной части методаasync
выполнить в потоке пула потоков. Я использую это в моем примере выше, чтобыProcessData
выполнялся в потоке пула потоков, точно так же, как при использованииSocketAsyncEventArgs
. -
Socket.Connected
бесполезен. Вам нужно отправить данные, чтобы определить, действительно ли соединение действительно.