mik*_*ksh 5 c# timeout tcpclient
通过超时取消TcpClient ReadAsync操作并在.NET 4.5中捕获此超时事件的正确方法是什么?
TcpClient.ReadTimeout似乎应用于同步只读.
更新:
Tried tro应用此处描述的方法取消异步操作
var buffer = new byte[4096];
CancellationTokenSource cts = new CancellationTokenSource(5000);
int amountRead = await tcpClientStream.ReadAsync(buffer, 0, 4096, cts.Token);
Run Code Online (Sandbox Code Playgroud)
但它永远不会超时取消.有什么问题吗?
Kha*_*mar 13
所以我知道这是很长一段时间,但谷歌仍然把我带到这里,我看到没有标记为答案
对我来说,我解决这个问题,我做了一个扩展,添加一个额外超时的方法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;
}
Run Code Online (Sandbox Code Playgroud)
所以如果它返回-1表示读取超时
编辑:以下要点是我为此所做的解决方法。 https://gist.github.com/svet93/fb96d8fd12bfc9f9f3a8f0267dfbaf68
原来的:
我真的很喜欢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;
}
}
Run Code Online (Sandbox Code Playgroud)
它或多或少是相同的东西,只是格式略有不同(对我来说)更具可读性,更重要的是它不使用Task.Run我不确定为什么在他的示例中使用它。
编辑:
乍一看上面的内容似乎不错,但我发现它会导致一些问题。如果没有数据进入,readAsync 调用似乎会泄漏,在我的例子中,它似乎读取了稍后的写入,并且数据本质上是在内存中不再使用的位置返回的。