2013-04-29 7 views
2

Я относительно новый для использования шаблона Async для чтения потока и записи, и спрашиваю, если ответ на этот вопрос настолько очевиден, он нигде не написано явно:Когда же поток EndRead блокировать обратный вызов

При вызова a NetworkStream.BeginRead, я передаю параметр обратного вызова, который согласно MSDN выполняется «когда BeginRead завершает». В нем также говорится, что «ваш метод обратного вызова должен вызывать метод EndRead».

Затем в соответствии с документацией для NetworkStream.EndRead «метод завершает асинхронную операцию чтения, запущенную методом BeginRead». В нем также упоминается, что этот метод «блокируется до тех пор, пока данные не будут доступны».

Я знаю, что метод EndRead также полезен для определения количества полученных байтов.

Мой вопрос:

Если метод EndRead вызывается в функции обратного вызова BeginRead, это когда-либо действительно блокировать? Не завершена ли операция чтения при вызове обратного вызова?

Пример кода

byte[] streamBuffer = new byte[1024]; 

    public void SomeFunction() 
    { 
     TcpClient client = new TcpClient(); 
     client.Connect(IPAddress.Parse("127.0.0.1"), 32000); 

     NetworkStream stream = client.GetStream(); 

     stream.BeginRead(streamBuffer,0,streamBuffer.Length,ReadCallback,stream); 
    } 

    public void ReadCallback(IAsyncResult ar) 
    { 
     NetworkStream stream = ar.AsyncState as NetworkStream; 

     // Will this call ever actually "block" or will it 
     // return immediately? Isn't the read operation 
     // already complete? 
     int bytesRead = stream.EndRead(ar); 

     // Other stuff here 
    } 
+1

Пожалуйста, разместите код. – spender

ответ

1

Операция чтения всегда завершена, когда срабатывает обратный вызов. Завершение - это то, что вызывает обратный вызов, в первую очередь. Поэтому EndRead() никогда не будет блокировать, когда он используется в методе обратного вызова.

Обратите внимание, что «завершено» также может означать «сбой», EndRead() генерирует исключение. Очень распространенное исключение - ObjectDisposedException, которое генерируется при закрытии сокета при выполнении асинхронного чтения. Обычно, когда вы выходите из программы, обязательно поймайте ее.

0

Нет, потому что метод EndRead вызывается (и блокировки) в делегат, который вызывается асинхронно. Итак, да, метод с EndRead блокирует, но не на потоке выполнения, который называется BeginRead.

+2

Вызов может быть «блокирующим» вызовом, но действительно ли он блокирует поток делегата? Не имеет ли конечное условие для блока EndRead, который уже завершен до его вызова? – nicholas

1

Вы можете использовать EndRead в двух ситуациях:

  • Вы можете использовать EndRead в заднем вызове функции. В этот момент ничего не будет заблокировано.
  • Вы также можете использовать EndRead без обратного вызова функции:

    myStream.BeginRead (...);
    // Выполняйте много работы одновременно.
    // Когда моя работа закончена, подождите, пока поток завершит свою работу.
    myStream.EndRead (...);

EndRead всегда должен быть вызван, чтобы сообщить о некоторых ошибках. Если произошла ошибка, EndRead выдает исключение.

+0

Но нужен ли EndRead в обратном вызове?Я видел примеры, где он никогда не используется. – nicholas

+0

Это плохие примеры. Да, *** каждый *** вызов BeginXXX должен быть сопряжен с вызовом EndXXX при использовании APM. Лично, с появлением 'async/await' .net4.5 и C# 5, я бы подумал, что эти API будут эффективно устаревать в любом случае. – spender

+0

@spender: Почему эти плохие примеры? Он считает, что он точно отвечает на его вопрос. Его вопрос не был: «Могу ли я использовать другой/лучший способ»? Он спрашивал, когда EndRead будет блокировать. И perhapse он не использует .NET4.5. –

Смежные вопросы