2016-02-05 102 views
0

我正嘗試使用Xamarin Android C#在藍牙打印機上讀取/寫入字節。我正在使用System.IO.Stream來做到這一點。不幸的是,每當我試圖對這些我碰到下面的錯誤流使用ReadTimeoutWriteTimeout如何在此流上不支持超時時實現.NET Stream超時

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

我不希望我的Stream.Read()Stream.Write()呼叫無限期地阻塞。我該如何解決這個問題?

回答

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 
0

你可能想用暴露的取消方法令牌,以便您的API可以easliy消耗。

其中一個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(),因爲它已不再適用於某些PCLS .Close() vs .Dispose()

+0

有沒有辦法用Read()方法來做到這一點還是必須使用ReadAsync()? – gonzobrains

+0

您應該可以通過Read()獲得相同的結果。 – interjaz

+0

我在問,因爲我沒有看到任何採用CancellationToken的Read()方法。 – gonzobrains