www.mikrocontroller.net

Forum: PC-Programmierung Suche C# Profi!


Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Chris ... (dechavue)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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)

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Chris ... (dechavue)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Chris ... (dechavue)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Chris ... (dechavue)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Chris ... (dechavue)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was du noch veruchen könntest:
try{
  port.DataRecieved -= DataRecFunc; //selbiges für alle abonierten Events
  port.Dispose();
  port = null;
  GC.Collect(); //Sofortiges aufräumen erzwingen um Exception zu provozieren
} catch (AccessVioltionException) {} 

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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!

Autor: Andy (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier noch ein detailierter Auszug der Fehlermeldung!

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Keiner vielleicht noch eine Idee??

Autor: Christian Aurich (cau) Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
geb doch mal deinen Code an, der nicht funktioniert... sonst müssen wir 
Raten, was sein könnte.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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
private void button1_Click(object sender, EventArgs e)
{
 if (ComPort == null)
 {
  ComPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
  ComPort.Open();
 }
}

private void button2_Click(object sender, EventArgs e)
{
 if (ComPort != null)
 {
  try
  {
   ComPort.Close();
//  ComPort.Dispose();
   oComPort = null;
   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.
  }
  catch (UnauthorizedAccessException) { } // übergangen
  catch (AccessViolationException) { } // übergangen
  catch (Exception) { } // übergangen
  catch { } // übergangen
 }
}

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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
static class Program
{
 /// <summary>
 /// The main entry point for the application.
 /// </summary>
 [STAThread]
 static void Main()
 {
  AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

  Application.EnableVisualStyles();
  Application.SetCompatibleTextRenderingDefault(false);
  Application.Run(new Form1());
 }

 static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
 {
  if (e.ExceptionObject.GetType() == typeof(UnauthorizedAccessException))
  {
   UnauthorizedAccessException ex = (UnauthorizedAccessException)e.ExceptionObject;
   MessageBox.Show(ex.Message);
  }
 }
}

Autor: Dave (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Stefan,

hab das problem zwar noch nciht gehabt, hab aber einen Link gefunden der 
dir eventuell hilft:
http://www.switchonthecode.com/tutorials/csharp-tu...

der Behandelt außerdem noch die ThreadException. vielleicht hilfts ja.

Grüße Dave

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Dave (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Dave,
ja genau. Thread.Sleep(..) und die MessageBox.Show(..) haben keine 
Auswirkung auf das Beenden des Programms.

Grüße,
Stefan

Autor: Arc Net (arc)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...
    public partial class SafeSerial : SerialPort {
        public SafeSerial() : base() {
        }

        public SafeSerial(System.ComponentModel.IContainer iC) : base(iC) { 
        }
 
        public SafeSerial(string portName) : base(portName) {
        }

        public SafeSerial(string portName, int baudRate)
            : base(portName, baudRate) {
        }

        public SafeSerial(string portName, int baudRate, Parity parity)
            : base(portName, baudRate, parity) {
        }

        public SafeSerial(string portName, int baudRate, Parity parity, int dataBits) 
            : base(portName, baudRate, parity, dataBits) {
        }

        public SafeSerial(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits) 
            : base(portName, baudRate, parity, dataBits, stopBits) {
        }
       
        public new void Open() {
            try {
                base.Open();
                // suppress finalize
                GC.SuppressFinalize(BaseStream);
            } catch {
            }
        }

        public new void Dispose() {
            Dispose(true);
        }

        protected override void Dispose(bool disposing) {
            if (disposing && (base.Container != null)) {
                Container.Dispose();
            }

            try {
                // try to finalize stream and catch all exceptions
                GC.ReRegisterForFinalize(BaseStream);
            } catch {
            }
            try {
                base.Dispose(disposing);
            } catch {
                // Prolific 
            }
        }
    }

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.