2014-02-08 4 views
3

При выполнении этого кода:Получение IOException с NetworkStream.BeginRead()

private async void StartChat(Object obj) 
{ 
    TcpClient me = (TcpClient)obj; 
    UpdateChatBox("Attempting read from server."); 
    myBuffer = new byte[BUFFER_SIZE]; 

    while (true) 
    { 
     var myStream = me.GetStream(); 
     myStream.BeginRead(myBuffer, 0, BUFFER_SIZE, new AsyncCallback(UpdateChatBoxAsync), myStream); 

     if (messageToSend) 
     { 
      await myStream.WriteAsync(myMessage, 0, myMessage.Length); 
     }     
    } 
} 

Я получаю следующее исключение ввода-вывода из BeginRead:

Невозможно прочитать данные из транспортного соединения: Операция сокета не может быть выполнена, потому что в системе недостаточно места для буфера или потому, что очередь заполнена.

Вот метод обратного вызова для BeginRead:

private void UpdateChatBoxAsync(IAsyncResult result) 
{ 
    var stream = result.AsyncState as NetworkStream; 
    int bytesRead = stream.EndRead(result); 

    if (bytesRead > 0) 
    { 
     String newMessage = NetworkUtils.GetString(myBuffer); 
     UpdateChatBox(newMessage); 
    } 
} 

Может кто-то пожалуйста, пролить некоторый свет, по той причине, что это исключение, которого воспитали? Я попытался воссоздать буфер каждый раз в начале цикла while, но пока это не улучшало исключение, я не получал сообщения с сервера.

Я также попытался сбросить myBuffer на пустой массив в конце UpdateChatBoxAsync, это тоже не сработало.

Любая помощь будет оценена по достоинству.

+2

Это низкоуровневая ошибка Windows, WSAENOBUFS. Довольно необычно, чтобы получить это при вызове BeginRead. Может быть [исчерпание пула ядра] (http://technet.microsoft.com/en-us/library/7a44b064-8872-4edf-aac7-36b2a17f662a.aspx), может быть, у вас слишком много открытых сокетов. –

ответ

2

Вы запуская бесконечный цикл без дросселирования. Вы выдаете асинхронные запросы чтения так же быстро, как это может сделать CPU. Это создает неограниченное количество выдающихся операций.

Предполагается, что вы прочитаете следующее, когда последний из них завершен (чаще всего выполняется с обратного вызова).

просто добавив

if (myStream.DataAvailable) 

избежать чтения, но все еще сгореть одно ядро ​​процессора. Это всего лишь смягчение одного из симптомов. Исправьте основную причину.

Кажется, вы не должны делать async IO вообще, потому что у вас нет проблем с блокировкой. Вы блокируете поток и сжигаете 100% ядра. Если это приемлемо, даже не беспокойтесь о async IO.

Или, используйте await ReadAsync.

+0

Итак, как вы думаете, как будет выглядеть правильное решение? Зачем использовать функцию ReadAsync для исправления этой проблемы? Просто ищите некоторую ясность. Благодаря!! – TGreg

+0

'await ReadAsync' продолжает обработку только после завершения текущего чтения. Это ключ. – usr

+0

Разделяет ли BeginRead собственный поток? – TGreg

0

Я нашел свое решение.

Перед пробуя BeginRead я проверяю, если поток имеет какие-либо данные, доступные с помощью NetworkStream.DataAvailable или в моем случае myStream.DataAvailable

Таким образом, новый рабочий блок кода выглядит

if (myStream.DataAvailable){ 
    myStream.BeginRead(myBuffer, 0, BUFFER_SIZE, new AsyncCallback(UpdateChatBoxAsync), myStream); 
} 
+0

Проверьте использование вашего процессора, возможно, сжигающее 100% на одном ядре, так как это бесконечный цикл без блокировки. – Haukman