2013-03-07 117 views
3

通过超时取消TcpClient ReadAsync操作并在.NET 4.5中捕获此超时事件的正确方法是什么?通过超时取消C#4.5 TcpClient ReadAsync

TcpClient.ReadTimeout似乎应用于同步只读。

UPDATE:
试图申请禁制令这里desribed Cancelling an Asynchronous Operation

var buffer = new byte[4096]; 
CancellationTokenSource cts = new CancellationTokenSource(5000); 
int amountRead = await tcpClientStream.ReadAsync(buffer, 0, 4096, cts.Token); 

的做法,但它永远不会被超时取消。有什么问题吗?

+1

我在'TcpClient'上看不到'ReadAsync'。 – leppie 2013-03-07 14:35:19

+0

对不起,这是NetworkStream.ReadAsync – miksh 2013-03-07 15:02:38

回答

0

你必须自己实现它:它不适用于该类。

你应该使用一个定时器,它会在一个时间间隔后终止异步操作,或者在后台线程中使用读同步版本。

那里你可以找到一个例子:Implementing a timeout with NetworkStream.BeginRead and NetworkStream.EndRead

+0

我正在寻求一个优雅的解决方案,利用.NET 4.5异步/任务功能。你能提供例子吗? – miksh 2013-03-07 15:05:07

+1

@miksh对不起。我回答了你的问题,并告诉你如何实现它。我想你可以自己做。 – giammin 2013-03-07 15:11:53

7

,所以我知道那是从很久 但谷歌仍然把我在这里 ,我看到有没有标记为答案

对我来说,我解决这样的 我做的扩展,添加一个方法ReadAsync是需要额外的超时

 public static async Task<int> ReadAsync(this NetworkStream stream, byte[] buffer, int offset, int count, int TimeOut) 
    { 
     var ReciveCount = 0; 
     var receiveTask = Task.Run(async() => { ReciveCount = await stream.ReadAsync(buffer, offset, count); }); 
     var isReceived = await Task.WhenAny(receiveTask, Task.Delay(TimeOut)) == receiveTask; 
     if (!isReceived) return -1; 
     return ReciveCount; 
    } 

所以如果它返回-1意味着读超时

0

原文:

我真的很喜欢回答Khalid Omar,并做了我自己的版本,我认为是值得分享:

public static class TcpStreamExtension 
{ 
    public static async Task<int> ReadAsyncWithTimeout(this NetworkStream stream, byte[] buffer, int offset, int count) 
    { 
     if (stream.CanRead) 
     { 

      Task<int> readTask = stream.ReadAsync(buffer, offset, count); 
      Task delayTask = Task.Delay(stream.ReadTimeout); 
      Task task = await Task.WhenAny(readTask, delayTask); 

      if (task == readTask) 
        return await readTask; 

     } 
     return 0; 
    } 
} 

这或多或少是同样的事情,除了稍有不同格式以一种更可读的方式(对我来说),更重要的是它不使用Task.Run我不确定它为什么用在他的例子中。

编辑:

上面似乎在乍看之下不错,但我发现它会导致一些问题。如果没有数据进来,readAsync调用似乎会泄漏,在我看来,它似乎读取稍后的写入,并且数据基本上在不再使用的内存中返回。