Guten Abend allerseits? Ich suche einen C#-Profi, der mir vielleicht bei meinem Problem helfen kann. Und zwar geht es um einen virtuellen COM-Port, der von einem FDTI-Chip erzeugt wird. Eigentlich läuft alles einwandfrei, nur: Wenn ich während der Laufzeit des Programmes den FDTI-Chip vom USB-Port entferne, fange ich das mit der WndProc-Methode (die vom System zur Verfügung steht) ab. Schließe ich danach das Device wieder an, kann ich mich auch wieder mit der virtuellen Schnittstelle verbinden und damit arbeiten. Aber wenn ich dann mein Programm beende kommt eine Access-Violation (irgendwas mit "...auf Port kann nicht zugegriffen werden...). Diese Fehler passiert nur, wenn ich das Device im Betrieb einmal entfernt habe. Tue ich das nicht, beendet das Programm einwandfrei. Das komische daran ist, dass ich das Port in der FormClosing-Methode (wie es sein soll) "close". Aber der Fehler passiert erst beim Beenden der "main"-Methode - keine Ahnung, was er da noch vom COM-Port will. Ich weiß, dass ich diesen Fehler hier nicht ausführlich genug beschrieben habe, aber vielleicht gibt mir auf Anhieb helfen kann, oder einen der das gleiche Problem mal hatte und mir ein paar Ansätze geben kann! Also, vielen Dank schon mal! mfg Andy
Hi, So direkt kann ich dir leider auch nicht sagen worans liegt, aber poste doch mal deinen Code zum zwischenzeitlichen Trennen bzw. neu aufbauen der Verbindung und den Stacktrace der Exception, eventuell kann ich dir dann helfen. greets (Eine schmutzige Lösung wäre, die Access-Violation-Exception zu fangen und zu ignorieren. Das beseitigt dann zwar die Symthome aber nicht die Ursache)
Hallo, Danke für deine Antwort. Bin gerade nicht in der Firma - werden versuchen, morgen eine Code-Schnippsel zu posten. Die Exception zu fangen habe ich auch schon versucht, aber das blöde ist, dass der Fehler passiert, wenn die "main"-Methode verlassen wird, d.h. wenn die schließende geschwungene Klammer erreicht ist. Und dort kann ich leider keinen Code mehr ausführen. Keine Ahnung, was da los ist! mfg
Für den Fall, daß Du die SerialPort-Klasse verwendest, rufst Du nach dem Close und vor dem Reconnect die Dispose-Methode auf? Ich hatte mal ein ähnlich gelagertes Problem mit (fehlendem) Graphics.Dispose. Gruß Markus
Markus wrote: > Für den Fall, daß Du die SerialPort-Klasse verwendest, rufst Du nach dem > Close und vor dem Reconnect die Dispose-Methode auf? Dispose sollte nicht nötig sein wenn Close() verwenet wird, da Close() auch den Internen Stream Disposed (siehe MSDN). Ich vermute eher, dass kein Close aufgerufen wird, sondern beim Reconnecten einfach ein neues Serialport-Objekt angelegt wird, und das andere undisposed im Speicher bleibt. Wenn ein Event (z.B. DataReceived) aboniert ist, wird es auch nicht von der GarbageCollection eingesammelt bist das Programm beendet wird.
Das mit dem Close() habe ich mir auch schon gedacht und auch probiert! Hat leider nichts genützt. Kann ja auch nicht funktionieren, weil ja kein COM-Port mehr vorhanden ist, wenn ich den FDTI entferne, oder?? Dann kann ich ja auch keinen mehr "closen". Liege ich da richtig?? Ich habe auch schon die Objektreferenz (mit "Serial=null") nach dem Entfernen des Devices gelöscht, ohne Erfolg! Vielleicht noch eine Idee?
Andy wrote: > Ich habe auch schon die Objektreferenz (mit "Serial=null") nach dem > Entfernen des Devices gelöscht, ohne Erfolg! Das entfernt das Objekt nicht, das bleibt aus oben genannten Grund noch vorhanden. Du musst das Serialport-Objekt Closen/Disposen auch wenn die eigentliche Schnittstelle nicht mehr vorhanden ist. Eventuell provozierst du damit direkt die AccessViolationException, aber dann ist es denke ich legitim sie hier einfach zu Fangen und zu ignorieren.
Wie gesagt, das hab ich auch schon probiert - werds aber nochmal versuchen! Fangen kann ich sie aus dem Grund nicht, weil der Fehler erst beim Verlassen der "main"-Methode passiert, d.h. die schließende geschwungene Klammer erreicht wird. Komischerweise ist das auch keine übliche Fehlermeldung, weil die Schaltfläche "Weiter" auf der Fehlermeldung angezeigt wird. Wird diese geklickt, läuft der Code ganz normal weiter. Vielleicht ist das ein nützlicher Hinweis. In der fertige exe wirkt sich der Fehler durch die berühmte "Anwendung musste geschlossen werden ... Bericht senden ...") aus.
Ich hatte gehofft, das durch das Close/Dispose die Exception sofort provoziert wird, dann hätte man eine Stelle an dem man sie abfangen kann.
Was du noch veruchen könntest:
1 | try{ |
2 | port.DataRecieved -= DataRecFunc; //selbiges für alle abonierten Events |
3 | port.Dispose(); |
4 | port = null; |
5 | GC.Collect(); //Sofortiges aufräumen erzwingen um Exception zu provozieren |
6 | } catch (AccessVioltionException) {} |
Hallo, Hab deinen Code-Schnippsel probiert - hat leider auch nichts genutzt. Aber ich bin draufgekommen, dass es kein "AccessViolationException" ist, sondern eine "UnauthorizedAccessException". Vielleicht hilft das weiter!
geb doch mal deinen Code an, der nicht funktioniert... sonst müssen wir Raten, was sein könnte.
Hallo, ich habe genau das gleiche Problem, auch in C#. Ich habe einen FTDI, der mir über USB einen RS232 Port zur Verfügung stellt. Wird nun die Verbindung vom USB unterbrochen, stürzt das Programm ab, sobald der Garbage Collector versucht, die von der Klasse des seriellen Ports belegten Resourcen wieder freizugeben. Die Exception lässt sich nicht fangen. Es scheint so, als würde meinem Programm während des Betriebs das Handle von Windows aus der Hand gerissen. Auf das nötigste reduziert sieht die Anwendung so aus: Es handelt sich einfach um ein Fenster mit zwei Schaltflächen. Wird die erste betätigt, wird der COM-Port geöffnet. Bei Betätigung der zweiten Schaltfläche wird er wieder geschlossen. Es werden in der Zeit dazwischen keine Daten ausgetauscht. Öffnet und schließt man den Port lediglich, funktioniert alles ohne Probleme. Trennt man zwischenzeitlich die USB Verbindung, entfernt also den COM-Port, dann stürzt das Programm ab, sobald man den Garbage Collector (GC.Collect()) aufruft. Dabei spielt es keine Rolle, ob das Gerät wieder angeschlossen wurde oder nicht. Ruft man den Garbage Collector nicht auf, dann stürzt das Programm einige Zeit später ab. Sicherlich, wenn der GC "etwas Zeit gefunden" hat. Spätestens jedoch, wenn das Programm beendet wird. Schonmal vielen Dank, Stefan
1 | private void button1_Click(object sender, EventArgs e) |
2 | { |
3 | if (ComPort == null) |
4 | { |
5 | ComPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One); |
6 | ComPort.Open(); |
7 | } |
8 | } |
9 | |
10 | private void button2_Click(object sender, EventArgs e) |
11 | { |
12 | if (ComPort != null) |
13 | { |
14 | try |
15 | { |
16 | ComPort.Close(); |
17 | // ComPort.Dispose(); |
18 | oComPort = null; |
19 | GC.Collect(); // <= Wenn der COM Port im System nicht mehr vorhanden ist/war, führt der Aufruf am Ende der Funktion zum Absturz des Programms. |
20 | } |
21 | catch (UnauthorizedAccessException) { } // übergangen |
22 | catch (AccessViolationException) { } // übergangen |
23 | catch (Exception) { } // übergangen |
24 | catch { } // übergangen |
25 | } |
26 | } |
Hallo, unterdessen habe ich herausbekommen, dass man mit folgendem Code die Exception fangen kann. Leider wird das Programm aber zu schnell beendet, als dass man die MessageBox auch wirklich lesen, geschweige denn irgend eine Interaktion damit durchführen könnte. Entsprechend kann man das Beenden des Programms leider auch nicht verhindern. Ich bin für alle Anregungen offen, die mir helfen, dieses Problem zu beheben. Grüße, Stefan
1 | static class Program |
2 | { |
3 | /// <summary> |
4 | /// The main entry point for the application. |
5 | /// </summary> |
6 | [STAThread] |
7 | static void Main() |
8 | { |
9 | AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); |
10 | |
11 | Application.EnableVisualStyles(); |
12 | Application.SetCompatibleTextRenderingDefault(false); |
13 | Application.Run(new Form1()); |
14 | } |
15 | |
16 | static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) |
17 | { |
18 | if (e.ExceptionObject.GetType() == typeof(UnauthorizedAccessException)) |
19 | { |
20 | UnauthorizedAccessException ex = (UnauthorizedAccessException)e.ExceptionObject; |
21 | MessageBox.Show(ex.Message); |
22 | } |
23 | } |
24 | } |
Hi Stefan, hab das problem zwar noch nciht gehabt, hab aber einen Link gefunden der dir eventuell hilft: http://www.switchonthecode.com/tutorials/csharp-tutorial-dealing-with-unhandled-exceptions der Behandelt außerdem noch die ThreadException. vielleicht hilfts ja. Grüße Dave
Hallo Dave, danke für den Link. Leider brachte dieser keine neuen Erkenntnisse. Der dort beschriebene Ansatz war mir bereits bekannt. Das Problem bei meiner Anwendung ist, dass eben wirklich das AppDomain.CurrentDomain.UnhandledException Event aufgerufen und die Software damit beendet wird. Damit habe ich mich auch bereits abgefunden. Ich kann den Nutzer nur leider nicht informieren, was denn eigentlich passiert ist, da die Anwendung zu schnell im Nirvana verschwindet. Vielen Dank, Stefan
Hi Stefan. Wenn ich das richtig verstehe, dann bleibt deine Applikation icht stehen bei MessageBox.Show oder? Billige Möglichkeit für Zeit ist natürlich ein THread.Sleep. Ich nehm an du hast es schon probiert bzw. es bleibt nicht stehen, da ja auch deine Message Box im Nirvana verschwindet. Ich kuck nochmalo bmir was einfaällt. Grüße Dave
Hallo Dave, ja genau. Thread.Sleep(..) und die MessageBox.Show(..) haben keine Auswirkung auf das Beenden des Programms. Grüße, Stefan
Stefan schrieb: > Hallo, > ich habe genau das gleiche Problem, auch in C#. Ich habe einen FTDI, der > mir über USB einen RS232 Port zur Verfügung stellt. Wird nun die > Verbindung vom USB unterbrochen, stürzt das Programm ab, sobald der > Garbage Collector versucht, die von der Klasse des seriellen Ports > belegten Resourcen wieder freizugeben. Die Exception lässt sich nicht > fangen. > Es scheint so, als würde meinem Programm während des Betriebs das Handle > von Windows aus der Hand gerissen. > Auf das nötigste reduziert sieht die Anwendung so aus: > Es handelt sich einfach um ein Fenster mit zwei Schaltflächen. Wird die > erste betätigt, wird der COM-Port geöffnet. Bei Betätigung der zweiten > Schaltfläche wird er wieder geschlossen. Es werden in der Zeit > dazwischen keine Daten ausgetauscht. Öffnet und schließt man den Port > lediglich, funktioniert alles ohne Probleme. Trennt man zwischenzeitlich > die USB Verbindung, entfernt also den COM-Port, dann stürzt das Programm > ab, sobald man den Garbage Collector (GC.Collect()) aufruft. Dabei > spielt es keine Rolle, ob das Gerät wieder angeschlossen wurde oder > nicht. Ruft man den Garbage Collector nicht auf, dann stürzt das > Programm einige Zeit später ab. Sicherlich, wenn der GC "etwas Zeit > gefunden" hat. Spätestens jedoch, wenn das Programm beendet wird. Das Problem ist MS schon länger bekannt (offizieller Fix in .NET 4) Aktueller Workaround: http://connect.microsoft.com/VisualStudio/feedback/Workaround.aspx?FeedbackID=140018
1 | public partial class SafeSerial : SerialPort { |
2 | public SafeSerial() : base() { |
3 | }
|
4 | |
5 | public SafeSerial(System.ComponentModel.IContainer iC) : base(iC) { |
6 | }
|
7 | |
8 | public SafeSerial(string portName) : base(portName) { |
9 | }
|
10 | |
11 | public SafeSerial(string portName, int baudRate) |
12 | : base(portName, baudRate) { |
13 | }
|
14 | |
15 | public SafeSerial(string portName, int baudRate, Parity parity) |
16 | : base(portName, baudRate, parity) { |
17 | }
|
18 | |
19 | public SafeSerial(string portName, int baudRate, Parity parity, int dataBits) |
20 | : base(portName, baudRate, parity, dataBits) { |
21 | }
|
22 | |
23 | public SafeSerial(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits) |
24 | : base(portName, baudRate, parity, dataBits, stopBits) { |
25 | }
|
26 | |
27 | public new void Open() { |
28 | try { |
29 | base.Open(); |
30 | // suppress finalize
|
31 | GC.SuppressFinalize(BaseStream); |
32 | } catch { |
33 | }
|
34 | }
|
35 | |
36 | public new void Dispose() { |
37 | Dispose(true); |
38 | }
|
39 | |
40 | protected override void Dispose(bool disposing) { |
41 | if (disposing && (base.Container != null)) { |
42 | Container.Dispose(); |
43 | }
|
44 | |
45 | try { |
46 | // try to finalize stream and catch all exceptions
|
47 | GC.ReRegisterForFinalize(BaseStream); |
48 | } catch { |
49 | }
|
50 | try { |
51 | base.Dispose(disposing); |
52 | } catch { |
53 | // Prolific
|
54 | }
|
55 | }
|
56 | }
|
Hallo Arc Net, Du bist mein heutiger Held des Tages. Deine Hilfe hat das Problem vollständig gelöst. Selbst der Kompromiss, dass die Applikation beendet wird, muss nun nicht mehr eingegangen werden. Vielen Dank (auch an Dave). Grüße, Stefan
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.