Problem mit SerialPort

7

Ich arbeite mit SerialPort, um mit dem Strichcodeleser zu kommunizieren (nur lesen).

Ich habe den Treiber so installiert, dass er mit dem Leser funktioniert, als wäre er über den Com-Port verbunden, obwohl es ein USB-Gerät ist. Wenn das Gerät eingesteckt ist, erscheint ein weiterer Com-Port in der Liste.

Das Problem ist das folgende. Ich initialisiere das SerialPort-Objekt, um es vom Barcodeleser zu lesen, aber wenn der Reader nicht angeschlossen ist, kann ich das SerialPort-Objekt nicht korrekt finalisieren oder entsorgen, weil der Port, an dem es angeschlossen ist, nicht mehr existiert.

Das Ergebnis ist WinIOException, wenn das Programm geschlossen wird. Ich kann es nicht nur im Code erkennen, der mit dem SerialPort arbeitet, sondern auch auf der Ebene von program.cs. Entsprechend dem Stack wird WinIOException nach den Versuchen, das SerialPort-Objekt zu finalisieren und zu disponieren, ausgelöst.

Gibt es irgendwelche Ideen, wie ich mit dieser Situation richtig umgehen kann? Oder zumindest um die Ausnahme zu fangen?

Was ich sicher weiß, ist, dass das Problem nicht in diesem speziellen Treiber liegt; Ich hatte noch einen Barcode-Leser von einem anderen Hersteller (mit dem gleichen Zweck Treiber) - die Situation ist die gleiche.

    
26071986 12.07.2010, 16:36
quelle

6 Antworten

12

Seufz, das ist ein uraltes Problem mit USB-Emulatoren für den seriellen Anschluss. Serielle Ports sind Geräte, die aus der Steinzeit stammen. Früher wurden sie in den Bus geschraubt, und sie konnten nicht entfernt werden, während ein Programm sie benutzte, ohne Funken und Rauch zu erzeugen. Steinzeit umfasst auch das Fehlen jeglicher Art von Plug-and-Play-Unterstützung, so dass ein Programm erkennen konnte, dass das Gerät plötzlich Gonzo ist.

Leider macht die Mehrzahl der Gerätetreiber, die sie emulieren, sie einfach verschwinden, obwohl ein Programm den Port geöffnet hat. Das funktioniert genauso gut wie ein Flash-Laufwerk aus dem Socket zu rucken, wenn Windows Dateien darauf schreibt. Es gibt einen Hintergrund-Worker-Thread, der auf Benachrichtigungen vom Gerätetreiber wartet, damit er die Ereignisse DataReceived, ErrorReceived und PinChanged generieren kann. Dieser Thread erleidet einen Herzinfarkt, wenn das Gerät plötzlich verschwindet. Sie können das nicht abfangen, es ist ein Thread, der von der SerialPort-Klasse gestartet wurde, Sie können ihn nicht mit try / catch umbrechen.

Auf vielfachen Wunsch hat Microsoft in .NET 4.0 etwas dagegen unternommen. Nicht wirklich sicher, was in dieser Version passiert. Wenn Sie in einer früheren Version stecken bleiben, können Sie nur ein Schild neben dem USB-Anschluss aufkleben: "Nicht entfernen, während Sie in Gebrauch sind!" Was unweigerlich dazu führt, dass jemand das Gerät mindestens zweimal ausschaltet, um zu sehen, was passiert. Danach langweilen sie sich und lassen Sie in Ruhe.

Die sehr unangemessene Problemumgehung ist eine app.exe.config-Datei mit diesem Inhalt:

%Vor%

Benutze es nicht.

    
Hans Passant 12.07.2010, 18:08
quelle
5

In meinem Code geschieht dies als Teil der Finalize() -Methode für den BaseStream, der vom Garbage Collector aufgerufen wird.

Wenn Sie also die .NET SerialPort-Klasse erben und das Öffnen / Schließen überschreiben, können Sie Folgendes tun:

Rufen Sie während des Öffnens einfach GC.SuppressFinalize(Me.BaseStream)

auf

Versuchen Sie beim Schließen, GC.ReRegisterForFinalize(Me.BaseStream)

aufzurufen

Wenn der USB-Stick herausgezogen wurde, löst dies eine Ausnahme aus und stöhnt über den Zugriff auf den BaseStream. Überprüfen Sie entweder die Eigenschaft .IsOpen , bevor Sie GC aufrufen, oder wickeln Sie sie in eine Try Catch ein, wenn Sie .IsOpen nicht vertrauen, um jedes Mal False zurückzugeben ...

Damit wird es fertig, Ihre Anwendung wird mit der Tatsache umgehen, dass sie ausgezogen ist, und beim Schließen wird sie nicht abstürzen.

Ich bin momentan nicht in der Lage, den Port wieder zu öffnen, wenn er wieder eingesteckt ist, aber zumindest gibt es einen Fortschritt, der über ein Label hinausgeht, das sagt, nicht anfassen ...

    
Chimpster 19.09.2011 12:35
quelle
2

Sie können von SerialPort erben und die Dispose () -Methode überschreiben, um solche Ausnahmen zu behandeln. Sie können die Ausnahme einfach verschlingen (Dispose sollte sowieso nicht werfen).

Wenn Sie die Ausnahme protokollieren oder auf andere Weise behandeln möchten, müssen Sie zuerst das disposing -Flag prüfen. Wenn es falsch ist, bedeutet dies, dass Dispose von Destructor von SerialPort aufgerufen wurde und das Objekt bereits verwaist ist.

z. B.

%Vor%     
Panagiotis Kanavos 12.07.2010 17:12
quelle
0

Nun, schlechte Nachrichten.

Lösung von Panagiotis Kanavos hilft nicht. Das Problem ist immer noch hier.

.Net 4.0 hilft auch nicht. Ich habe VS2010 installiert - nichts hat sich geändert. Die nicht abgeholte Ausnahme wird weiterhin ausgelöst. Leider, "Klebeband ein Zeichen neben dem USB-Steckplatz:" Nicht während der Verwendung entfernen! "Scheint die einzige Entscheidung zu sein ...

    
26071986 20.07.2010 09:53
quelle
0

Ich habe die gleiche Erfahrung gemacht. Obwohl dies nicht empfohlen wird, können Sie ein serielles Gerät ausstecken und an eine tatsächliche serielle Schnittstelle anschließen, und die Kommunikation beginnt erneut. Ein serieller USB-Anschluss funktioniert auf diese Weise nicht. Ich hatte auch das Problem, dass der serielle USB-Port von der Methode SerialPort.GetPortNames () nicht als verfügbarer Port angezeigt wurde, bis der virtuelle serielle Port von der Software instanziiert wurde.

    
skinnedKnuckles 06.11.2013 18:24
quelle
0

Ich habe dieses Problem gelöst, indem ich einen separaten Prozess erstellt habe, der den seriellen Port verwaltet. Wenn der serielle Port nicht angeschlossen ist, starte ich den Prozess neu. Jetzt kann ich die Verbindung zu einem unplugged seriellen Gerät wiederherstellen, ohne die Hauptanwendung neu zu starten.

  

TLDR; Erstellen Sie einen separaten Prozess.

Beispielcode

Prozesscode für den seriellen Port

%Vor%

Hauptanwendung

%Vor%     
Johan Andersson 27.04.2017 06:19
quelle

Tags und Links