c# - C# 在网络流上设置 WriteTimeout / ReadTimeout 没有区别?
问题描述
我的 Xamarin.Forms 应用程序中有以下方法代码
using (TcpClient client = new TcpClient(ip, port))
using (NetworkStream stream = client.GetStream())
{
byte[] messageBytes = PrepareMessageBytes();
//
// Setting these seam to have no effect
//
stream.WriteTimeout = (int)TimeSpan.FromSeconds(10).TotalMilliseconds;
stream.ReadTimeout = (int)TimeSpan.FromSeconds(10).TotalMilliseconds;
//
// I have set read and write timeouts above but when
// hitting this line, app hangs indefinitely?
// I would expect that after 10 seconds, a IOException
// will be thrown
await stream.WriteAsync(messageBytes, 0, messageBytes.Length);
stream.Flush();
byte[] buffer = new byte[1024];
StringBuilder builder = new StringBuilder();
int bytesRead = 0;
while (stream.DataAvailable)
{
bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
builder.AppendFormat("{0}", Encoding.ASCII.GetString(buffer, 0, bytesRead));
}
string msg = receivedMessage.ToString();
}
上面,我将写入和读取超时都设置为 10 秒。我知道我的代码挂在电话上:
等待流.WriteAsync(...)
,但我希望在 10 秒后,会抛出 IOException。根据 MS 文档,异步写入/读取并非如此。
如何设置对 WriteAsync / ReadAsync 方法的调用超时?
更新 - 基于斯蒂芬的评论的第二次尝试
根据 Stephen 的评论,我更新了代码并将其包装到 try..catch 中以处理 OperationCancelledException。但这现在比以前造成了更多的问题,并且应用程序大部分时间仍然会挂起:
try
{
using (TcpClient client = new TcpClient(ip, port))
using (NetworkStream stream = client.GetStream())
using (var writeCts = new CancellationTokenSource(TimeSpan.FromSeconds(10)))
{
byte[] messageBytes = PrepareMessageBytes();
await stream.WriteAsync(messageBytes, 0, messageBytes.Length, writeCts.Token);
await stream.FlushAsync();
byte[] buffer = new byte[1024];
StringBuilder builder = new StringBuilder();
int bytesRead = 0;
while (stream.DataAvailable)
{
using (var readCts = new CancellationTokenSource(TimeSpan.FromSeconds(10)))
bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, readCts.Token);
builder.AppendFormat("{0}", Encoding.ASCII.GetString(buffer, 0, bytesRead));
}
string msg = receivedMessage.ToString();
}
catch (OperationCancelledException ex)
{
Debug.WriteLine(ex.Message);
}
解决方案
如何设置对 WriteAsync / ReadAsync 方法的调用超时?
您使用带CancellationToken
参数的重载:
using (TcpClient client = new TcpClient(ip, port))
using (NetworkStream stream = client.GetStream())
using (var writeCts = new CancellationTokenSource(TimeSpan.FromSeconds(10)))
{
byte[] messageBytes = PrepareMessageBytes();
await stream.WriteAsync(messageBytes, 0, messageBytes.Length, writeCts.Token);
await stream.FlushAsync();
byte[] buffer = new byte[1024];
StringBuilder builder = new StringBuilder();
int bytesRead = 0;
while (stream.DataAvailable)
{
using (var readCts = new CancellationTokenSource(TimeSpan.FromSeconds(10)))
bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, readCts.Token);
builder.AppendFormat("{0}", Encoding.ASCII.GetString(buffer, 0, bytesRead));
}
string msg = receivedMessage.ToString();
}
我希望 10 秒后,会抛出 IOException。
使用取消令牌时,需要一个OperationCanceledException
. 从技术上讲,取消令牌可用于多种取消场景——代码决定不再需要完成操作、用户手动取消操作或发生超时。OperationCanceledException
是泛型异常类型,意思是“已取消”。
推荐阅读
- python - 检查谜语答案的 Python 程序
- ios - 使用我的 swift 4 应用程序在 firebase 中保存 json 数组
- javascript - Redux - npm 运行开发
- extjs - 如何仅在单击复选框而不是使用复选框选择模型的任何单元格上选择记录
- python - Revit Python 的 isinstance() 有问题
- postgresql - 使用orange3的模棱两可的列错误 - POSTGRES
- vb.net - 获取 MouseDown 和 DragDrop 的控件名称
- python - Python Split() 函数拆分无明显原因
- html - CSS 响应式边框半径图像
- c# - 所需的可执行文件的路径是什么