2

I am trying to read/write bytes to/from a Bluetooth printer using Xamarin Android in C#. I am making use of System.IO.Stream to do this. Unfortunately, whenever I try to use ReadTimeout and WriteTimeout on those streams I get the following error:

Message = "Timeouts are not supported on this stream."

I don't want my Stream.Read() and Stream.Write() calls to block indefinitely. How can I solve this?

gonzobrains
  • 7,856
  • 14
  • 81
  • 132

2 Answers2

0

You must do the reads on another thread; in this case if you must stop reading you can close the stream from other thread and the read will finish with an exception.

Another easy way is to use a System.Threading.Timer to dispose the stream:

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
gonzobrains
  • 7,856
  • 14
  • 81
  • 132
Gusman
  • 14,905
  • 2
  • 34
  • 50
0

You probably would like to expose an method with cancellation token so your api can be easliy consumed.

One of the CancellationTokenSource constructors takes TimeSpan as a parameter. CancellationToken on other hand exposes Register method which allows you close the stream and the reading operation should stop with an exception being thrown.

Method call

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

Method implementation

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
        }
    }
}

The following code will dispose stream only if it times out

More to can be found here.

Edit:

Changed .Close() to .Dispose() since it is no longer available in some PCLs .Close() vs .Dispose()

Community
  • 1
  • 1
interjaz
  • 193
  • 1
  • 1
  • 8