Laden...

Usb-Stream bzw. Handle wird nicht (richtig) geschlossen: SafefileHandle is invalid beim Neuöffnen

Erstellt von Gmi vor 10 Jahren Letzter Beitrag vor 10 Jahren 1.692 Views
Hinweis von herbivore vor 10 Jahren

Abgeteilt von "Merkwürdiges" Verhalten von Filestream.Close() bei USB Verbindung

G
Gmi Themenstarter:in
33 Beiträge seit 2008
vor 10 Jahren
Usb-Stream bzw. Handle wird nicht (richtig) geschlossen: SafefileHandle is invalid beim Neuöffnen

Nun hat sich leider ein weiteres Problem gezeigt: wenn ich die USB-Verbindung ein weiteres Mal öffne bekomme ich ein SafefileHandle, das invalid ist. Erst bei erneutem Start des Haupt-Programms kann ich die Verbindung wieder öffnen.

16.841 Beiträge seit 2008
vor 10 Jahren

Dann schließt Du wahrscheinlich irgendwo das/ein Handle nicht richtig bzw. gibst es nicht korrekt frei (Dispose etc)

U
1.688 Beiträge seit 2007
vor 10 Jahren

Ausgehend vom obigen Quellcode wird ja nur HsiPort geschlossen, nicht safeFileHandle.

16.841 Beiträge seit 2008
vor 10 Jahren

Wo in beiden Fällen ohnehin das Verwenden von using einiges erleichtern und verbessern würde.
Beim Handle reicht meist ein Close nicht aus, sondern ist auch ein Dispose erforderlich.

G
Gmi Themenstarter:in
33 Beiträge seit 2008
vor 10 Jahren

Vielen Dank für die Vorschläge.

Das Schließen der USB-Verbindung sieht so aus:


private void CloseHsiUsbConnection()
        {
            if (HsiPort != null) HsiPort.Close();
            if(safeFileHandle != null)
                try
                {
                    safeFileHandle.Close();
                }
                finally 
                {
                    safeFileHandle.Dispose();
                }
        }

Leider besteht das Problem weiterhin, dass ich beim erneuten Aufruf von CreateFile() einen ungültigen SafeFileHandle bekomme.

16.841 Beiträge seit 2008
vor 10 Jahren

Ohne jetzt auf den Fehler einzugehen: verstehst Du, was Dispose ist und verstehst Du, was Dein Code überhaupt macht?
Vermutlich nicht, das sieht man nämlich an Deinem Code. Und vermutlich ist es insgesamt ein Folgefehler, weil Du "irgendwas" tust - weil Du nicht verstehst, was Du machst -, statt dem, was man vermutlich tun muss.

PS: den Stream schließt Du zwar mit Close. Weil Du aber nirgends Dispose() des Streams ausführst, wird dessen Ressource/Handle (vermutlich) nicht komplett freigeben.
Ergo: ab an die Doku und mal nochmal die Grundlagen lernen, damit Du auch verstehst, was da überhaupt abläuft statt zu schustern.

S
248 Beiträge seit 2008
vor 10 Jahren

Hallo,

beide Close() Methoden rufen intern Dispose auf. Den Finally-Block kannst du damit weglassen.

Grüße

G
Gmi Themenstarter:in
33 Beiträge seit 2008
vor 10 Jahren

Hallo Abt, Du hast vollkommen recht, ich verstehe es nicht, sonst hätte ich mich nicht an das Forum gewendet.

16.841 Beiträge seit 2008
vor 10 Jahren

Wie Close oder Dispose funktioniert gehört zu den Grundlagen; das muss das Forum Dir nicht beibringen.
Was ich aber kritisiert hab ist: Du machst "irgendwas" ohne dass Du verstehen willst, was Du tust. Du machst halt mal was, probierst was ohne wirklich nachzudenken, wie das eigentlich alles funktioniert. Und das muss das Forum Dir eigentlich ebenfalls nicht alles beibringen. Wir sind keine Lehrer

Zum Problem: sorgt dafür, dass alle Handles ordnungsmäßig freigegeben werden.
Daher auch mein Hinweis: am besten using verwenden (und zwar für alles, was IDisposable implementiert). Inwieweit das die Programmlogik betrifft: auch das sind Programmiergrundlagen.

Wenn trotz Freigabe aller Handles es immer noch funktioniert könnte es am USB Treiber liegen; der macht hier ab und an zicken bei solchen Aktionen.

Was ich allgemein am Code bemängle: securityattributes der CreateFile-Schnittstelle will kein int, sondern ein IntPtr; empfängt damit (optional) eben IntPtr.Zero und nicht 0.
IntPtr.Zero repräsentiert NULL (nicht zu verwechseln mit C# null bzw. 0). Inwiefern das der Wrapper automatisch macht: weiß ich nicht. Könnte aber ein Fehler sein.
Änliches Spiel bei flags: das will eigentlich ebenfalls [MarshalAs(UnmanagedType.U4)]
Wenn ich mich dann richtig erinner will CreateFile in diesem Fall ein CharSet.Auto (bzw. ist das ohnehin bzgl. des Marshallers empfohlen). Du gibst gar nichts an und ist somit CharSet.Ansi. Könnte ebenfalls ein Fehler sein.

G
Gmi Themenstarter:in
33 Beiträge seit 2008
vor 10 Jahren

Hallo Abt, vielen Dank für die Erläuterungen.
Eine Änderung des Securityattributes von 0 in IntPtr.Zero löst das Problem leider nicht.

Ich habe das Problem vielleicht weiter eingrenzen können: Solange ich mit Filestream Read und Write auf das USB-Device zugreife, kann ich nach Beenden der USB-Verbindung diese erneut öffnen.

Erst wenn die asynchrone Datenübertragung gestartet wird, funktioniert das nicht mehr.

Hier meine Code:


private AsyncCallback _dataReadCallback;

private void WaitForData()
        {
            Byte[] hsiByteArray = new Byte[1500];
            try
            {
                if (_dataReadCallback == null)
                {
                   
                    _dataReadCallback = OnDataReceived;
                }

                HsiPort.BeginRead(
                    hsiByteArray, 0, hsiByteArray.Length, _dataReadCallback, new AsyncInfo(hsiByteArray, null));



            }
            catch (IOException ex)
            {
                MessageBox.Show(ex.Message);
            }
             
        }

        private void OnDataReceived(IAsyncResult asyn)
        {
            AsyncInfo info = asyn.AsyncState as AsyncInfo;
            try
            {
                int iRx = HsiPort.EndRead(asyn);
                if (iRx > 0)
                {
                    if (info != null)
                    {
                        this.ParseAnswer(info.ByteArray, iRx);
                    }
                }
                this.WaitForData();
            }
            catch (IOException ex)
            {
                MessageBox.Show(ex.Message);
            }
        }


Soweit ich es herausfinden konnte, sollte das Aufrufen von Filestram.Close() genügen um das asynchrone Lesen zu beenden.
Wenn ich safeFileHandle.Close() aufrufe und interher abfrage, ob das Handle die eigenschaft "IsClosed" hat, bekomme ich "false", das erklärt, warum ich keine neue Verbindung erstellen kann.

Was mache ich falsch? Wie schließe ich das SafeFileHandle korrekt?