2016-06-22 15 views
0

Ich verwende die DataWriter and DataReader Schnittstellen innerhalb einer using-Anweisung (IDisposable) geschieht. Diese Klassen haben die IDisposable-Schnittstelle implementiert, ich sie deshalb wickeln rund um die using Stichwort:.Handle Ausnahme, die

using(var datareader = new DataReader(SerialPortInputStream)) 
{ 
CancellationTokenSource cancellation = new CancellationTokenSource(); 
//Timeout 
cancellation.CancelAfter(1000); 
//... 
datareader.LoadAsync(120).AsTask(cancellation.Token); 
//Some fancy methods 
... 
//Last step: Detach the InputStream to use it again 
datareader.DetachStream(); 
} 

Dieser Thread here sagt, dass, wenn eine Ausnahme (hier ein "TaskCancelledException" innerhalb einer using-Anweisung geschieht, wird das Objekt angeordnet ist jetzt ist das Problem mit dem UWP- DataReader und DataWriter: Sie werden den zugrunde liegenden Stream schließen, wenn das Objekt angeordnet wird, um zu verhindern, dass ich anrufen datareader.DetachStream haben() und dann entsorgen

Wir nicht verwenden können.. DataReader/DataWriter mit einer using Anweisung, wenn wir den zugrunde liegenden InputStream/Outputstream später erneut benötigen. Ist diese Schlussfolgerung richtig oder gibt es andere Möglichkeiten, mit dieser Situation zu umgehen?

Antwort

1

Die ganze Bedeutung von using ist sicherzustellen, dass das Objekt am Ende des Blocks entsorgt wird, egal was passiert, ohne den gesamten Code dafür selbst schreiben zu müssen. Dies geschieht, indem das Objekt innerhalb eines finally Blocks angeordnet wird.

Was Sie versuchen zu tun ist datareader.DetachStream()vor nennen das Objekt angeordnet wird - wieder egal was passiert.

So würde meine Schlussfolgerung, dass die using Aussage hier nicht sehr hilfreich ist, und Sie sollten dies tun, indem Sie sich, vielleicht wie folgt aus:

DataReader datareader = null; 
try 
{ 
    datareader = new DataReader(SerialPortInputStream); 
    CancellationTokenSource cancellation = new CancellationTokenSource(); 
    //Timeout 
    cancellation.CancelAfter(1000); 
    //... 
    datareader.LoadAsync(120).AsTask(cancellation.Token); 
    //Some fancy methods 
    ... 
} 
finally 
{ 
    //Last step: Detach the InputStream to use it again 
    datareader?.DetachStream(); 
    datareader?.Dispose(); 
} 

So dies im Wesentlichen ist, was die using Anweisung, um Ihren Code tut , außer dass Sie den Anruf datareader?.DetachStream() einfügen können.


Hinweis, dass die datareader schließlich ohnehin auch ohne die Aussage using entsorgt bekommen würde. Wenn der Gültigkeitsbereich dieser Variablen verlassen wird, kann die Speicherbereinigung jederzeit entscheiden, diese Instanz aus dem Speicher zu entfernen, was zu einem Aufruf der Dispose-Methode führen würde. Daher wird ein Anruf an DetachStream() benötigt, bevor Sie das Scope verlassen.

+0

(In Bezug auf Ihre Anmerkung :) Ich habe es auf die harte Tour gelernt. Besonders wenn Sie den Stream erneut verwenden müssen: "Plötzlich" wird der Garbage Collector den Stream schließen und Ihre andere Methode "zerstören": Egal was passiert, rufen Sie immer 'DetachStream()' auf. – FikLi