Timeouts iniciantes / iniciantes
-
28-09-2019 - |
Pergunta
Estou usando um NetworkStream & TCPClient para receber dados de forma assíncrona usando o BEGINRAD. Preciso aplicar um tempo limite a esta operação, de modo que, após uma quantidade especificada de tempo, a leitura será abortada.
Até onde sou capaz de dizer, isso não é suportado no NetworkStream ou no TCPClient - existe uma propriedade RECEVETimeout, mas isso parece se aplicar apenas ao equivalente síncrono - 'Read'.
Mesmo a classe de soquete subjacente não parece suportar tempo limite em seu método iniciante.
Eu pesquisei sobre esse problema e a única resolução sugerida que vi é configurar outro thread de segundo plano para cancelar a operação se não concluir dentro do período de tempo limite. Parece um hack horrível. Certamente há uma maneira melhor?
Solução
É a única maneira de fazê -lo, porque quando você está usando uma operação assíncrona, o encadeamento que iniciou a operação está fazendo outra coisa. O tempo limite está disponível com a versão síncrona porque o thread de execução é bloqueado até que a operação de leitura seja concluída.
Se você precisar usar um encadeamento de segundo plano para cancelar a operação, não haveria muito sentido em continuar usando os métodos de início/final assíncronos. Se você quiser girar um encadeamento de segundo plano, basta executar uma operação de leitura síncrona a partir do encadeamento em segundo plano e, em seguida, poderá usar o RECEVETIMEOUT.
Outras dicas
Espere ManualResetevent com algum valor de tempo limite para sinalizar quando sua tarefa é concluída. Se ele se destacar antes de ser sinalizado, você sabe que a operação assíncrona nunca foi concluída.
private ManualResetEvent receiveDone = new ManualResetEvent(false);
receiveDone.Reset();
socket.BeginReceive(...);
if(!receiveDone.WaitOne(new TimeSpan(0, 0, 0, 30))) //wait for 30 sec.
throw new SocketException((int)SocketError.TimedOut);
Dentro de retorno de chamada para iniciantes, use
private void ReceiveCallBack(IAsyncResult ar)
{
/** Use ar to check if receive is correct and complete */
receiveDone.Set();
}