如果此流不支持超时,如何在.NET Stream上实现超时

时间:2016-02-05 18:46:29

标签: c# android .net xamarin bluetooth

我正在尝试使用C#中的Xamarin Android向/从蓝牙打印机读取/写入字节。我正在利用System.IO.Stream来做到这一点。不幸的是,每当我尝试在这些流上使用ReadTimeoutWriteTimeout时,我都会收到以下错误:

  

Message =“此流不支持超时。”

我不希望我的Stream.Read()Stream.Write()调用无限期阻止。我该如何解决这个问题?

2 个答案:

答案 0 :(得分:0)

你必须在另一个线程上进行读取;在这种情况下,如果您必须停止读取,则可以从其他线程关闭流,并且读取将以异常结束。

另一种简单的方法是使用System.Threading.Timer来处理流:

Stream str = //...

Timer tmr = new Timer((o) => str.Close());
tmr.Change(yourTimeout, Timeout.Infinite);

byte[] data = new byte(1024);
bool success = true;

try{  str.Read(data, 0, 1024);  }
catch{ success = false, }
finally{ tmr.Change(Timeout.Inifinite, Timeout.Infinite); }

if(success)
   //read ok
else
   //read timeout

答案 1 :(得分:0)

您可能希望公开一个带有取消令牌的方法,以便您的api可以轻松消耗。

其中一个CancellationTokenSource构造函数将TimeSpan作为参数。另一方面,CancellationToken暴露了Register方法,该方法允许您关闭流,并且读取操作应该在抛出异常时停止。

方法调用

var timeout = TimeSpan.Parse("00:01:00");
var cancellationTokenSource = new CancellationTokenSource(timeout);
var cancellationToken = cancellationTokenSource.Token;
await ReadAsync(stream, cancellationToken);

方法实施

public async Task ReadAsync(Stream stream, CancellationToken cancellationToken) 
{
    using (cancellationToken.Register(stream.Dispose))
    {
        var buffer = new byte[1024];
        var read = 0;
        while ((read = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
        {
            // do stuff with read data
        }
    }
}

以下代码仅在超时时才会处理流

更多可以找到here

编辑:

将.Close()更改为.Dispose(),因为某些PCL中不再提供它.Close() vs .Dispose()