C# 如何在不关闭流的情况下取消NetworkStream.ReadAsync
我正在尝试使用NetworkStream.ReadAsync()读取数据,但我找不到如何在调用ReadAsync()后取消它。对于后台,NetworkStream由连接的BluetoothClient对象(来自32Feet.NET Bluetooth库)提供给我 下面是我正在尝试的当前GetIt工作代码C# 如何在不关闭流的情况下取消NetworkStream.ReadAsync,c#,.net,asynchronous,async-await,networkstream,C#,.net,Asynchronous,Async Await,Networkstream,我正在尝试使用NetworkStream.ReadAsync()读取数据,但我找不到如何在调用ReadAsync()后取消它。对于后台,NetworkStream由连接的BluetoothClient对象(来自32Feet.NET Bluetooth库)提供给我 下面是我正在尝试的当前GetIt工作代码 int bytesRead; while (this.continueReading) { bytesRead = await this.stream.ReadAsync(this.b
int bytesRead;
while (this.continueReading)
{
bytesRead = await this.stream.ReadAsync(this.buffer, 0, (int)this.buffer.Length);
Console.WriteLine("Received {0} bytes", bytesRead);
}
Console.WriteLine("Receive loop has ended");
该代码在接收数据时工作正常,如果continueReading标志设置为false并接收到数据,则将停止循环,但在接收到数据之前,它不会继续通过ReadAsync()行。我看不出如何在不接收数据的情况下中止呼叫
我知道ReadAsync有一个重载,它提供了一个CancellationToken,但由于NetworkStream没有覆盖默认的ReadAsync行为,因此该令牌被忽略(请参阅)
我尝试关闭底层流,这会导致等待的ReadAsync调用抛出ObjectDisposedException,并且底层蓝牙连接也会关闭。理想情况下,我不想为了停止阅读而完全切断与设备的连接。这似乎不是一种干净的方法,而且感觉没有必要为了中断va ReadAsync()调用而中断整个流
有什么建议吗?您可以在NetworkStream.Read(或ReadAsync)周围实现一个异步包装器,该包装器还接收一个cancellationtoken,您可以监视并尊重自己。大概是这样的:
Task MyCancelableNetworkStreamReadAsync(NetworkStream stream, CancellationToken ct)
{
...
if(this.stream.CanRead)
{
do
{
//check ct.IsCancellationRequested and act as needed
bytesRead = await this.stream.ReadAsync(this.buffer, 0, (int)this.buffer.Length);
}
while(myNetworkStream.DataAvailable);
}
try {
....
Task<int> readTask = input.ReadAsync(buffer, 0, buffer.Length);
readTask.Wait(myCancellationToken);
int readBytes= await readTask;
....
}
catch ( OperationCanceledException e )
{
// handle cancellation
}
请注意,我只是试图说明这个想法,您可能不会考虑返回<代码>任务<代码>,以及是否在循环中拥有DO {}、任何额外的处理或清理等-全部根据您的需要。
我还要提醒您注意Stephen Toub的文章以及他在文章中创建的WithCancellation扩展。您不能取消ReadAsync,因为内部调用是非托管的,并且使用IOCompletion端口。。你的选择如下
我通过让任务在异步调用和wait语句之间等待取消令牌调用来管理取消,如下所示:
Task MyCancelableNetworkStreamReadAsync(NetworkStream stream, CancellationToken ct)
{
...
if(this.stream.CanRead)
{
do
{
//check ct.IsCancellationRequested and act as needed
bytesRead = await this.stream.ReadAsync(this.buffer, 0, (int)this.buffer.Length);
}
while(myNetworkStream.DataAvailable);
}
try {
....
Task<int> readTask = input.ReadAsync(buffer, 0, buffer.Length);
readTask.Wait(myCancellationToken);
int readBytes= await readTask;
....
}
catch ( OperationCanceledException e )
{
// handle cancellation
}
试试看{
....
Task readTask=input.ReadAsync(buffer,0,buffer.Length);
readTask.Wait(myCancellationToken);
int readBytes=等待读取任务;
....
}
捕捉(操作取消异常e)
{
//手柄取消
}
我忘了检查可用数据!感谢您提供示例代码和Stephen Toub文章的链接。两者都将有助于我实现我所追求的目标。谢谢不幸的是,我没有使用套接字,所以我不相信我可以使用Socket.Shutdown。我创建了一个BluetoothClient(从32Feet.NET)并调用BluetoothClient.Connect()。连接后,我通过BluetoothClient.GetStream()检索流。至于超时,MSDN说流的超时只适用于同步读取()——通过设置ReadTimeout属性确认,ReadAsync()从未超时。不过,关于检查套接字中可用数据的部分很有帮助,这是我完全忘记的。谢谢,我的阅读理解能力不好。我很高兴听到我的非相关答案仍然有用。如果使用TCPClient,TCPClient.Close()方法可用于在挂起的readAsync()调用上引发异常。您是否将此方法用于NetworkStream readAsync和WriteAsync?你能为两者提供一个很好的例子吗?感谢对Wait
的调用阻塞了线程,消除了使用ReadAsync
的好处。