none
Thread.Join() Blockiert. RRS feed

  • Frage

  • Hallo Zusammen,

    ich bin auf der Suche nach einer Erklärung und Problemlösung und bedanke mich im voraus für die Bemühungen.

    Für ein Projekt muss ich ein Modul erzeugen welches zyklisch aufgerufen wird. Mein Modul greift dafür asynchron auf eine Hardware zu wofür ich dieser asynchronen Aufgabe einen Thread spendiert habe. Dieser wird vom Programm per Interface 'start()' erzeugt und gestartet. Damit das Programm wieder sauber beendet werden kann wollte ich vom Programm das 'stop()' Interface verwenden, was soweit auch funktioniert. Leider hängt sich das Programm beim Thread.Join() auf. Wenn ich auf das Thread.Join() verzichte, wird die Schleife beendet aber das Programm besitzt nach Programmende immer noch diesen offenen Thread.

     

    Anbei ein Auszug des Moduls.

     

     class hardwareaccess : IModul

    {

           private volatile Thread _thr = null;

           private volatile bool _thrr = false;

           public void start()
            {
                if (_thr == null)
                {
                    _thr = new Thread(generate);
                    _thrr = true;
                    _thr.Start();

                    // Loop until worker thread activates.
                    while (!_thr.IsAlive) ;
                }
            }

            public void stop()
            {
                if (_thr == null) return;
                _thrr = false;
                Thread.Join();
                _thr = null;
            }

            private void generate()
            {
                while (_thrr)
                {
                    Thread.Sleep(10);

                    DelegateToCaller("ergebnisse");
                }
            }

    }

    Die Schleife wird erfolgreich beendet. Das konnte ich bereits mit Trace-Ausgaben nachvollziehen. Aber wie schon gesagt bleibt das Programm beim Join() hängen.

    An was kann dies Liegen?

     

    Vielen Dank. Smartic

    Freitag, 26. November 2010 08:12

Antworten

  • Hallo Smartic

    Join wartet auf das Ende des Thread, was bei dir nicht stattfindet.
    Ich sehe da zwei typische Ursachen, etwa in deinem Code stark anzunehmen: ein klassischer DeadLock, falls DelegateToCaller  gerade mit erstem Thread synchronisiert!

    Oder uU noch (in deinem Code nicht sichtbar), wenn der Thread derweil (direkt+indirekt) in unmanaged Code feststeht, was man bei deiner Aufgabe "asynchron auf eine Hardware"  genauer prüfen sollte.
       (während ein Thread in unmanaged Code, wird dein Abbruch-Flag nicht gepollt?)
    Freitag, 26. November 2010 08:58
  • Hallo Sm.,

    zunächst scheinst Du einen Fehler im Code zu haben. "Thread.Join();" scheint folgendes heissen zu sollen: "_thr.Join();".
    Aber mal angenommen, das wäre schon so, dann ist das Blockieren von "_thr.Join()" ist "by design", es blockiert den aufrufenden Thread, bis ein Thread beendet wird, (während das Standard-COM- und das SendMessage-Pumping fortgesetzt werden).

    Nimmt mal mal vereinfacht im DelegateCaller folgendes an:

       private void DelegateToCaller(string p)
       {
        Thread.Sleep(5000);
       }
    

    dann wartet also "_thr.Join();" natürlich so lange, bis der DelegateToCaller-Thread beendet ist!
    Je nach Inhalt von DelegateToCaller gibt es also vielerlei Möglichkeiten. In Deinem Fall können nun typischerweise Deadlocks und Racebedingungen auftreten. [Empfohlene Vorgehensweise für das verwaltete Threading].

    Insofern - wenn Du es jetzt nicht schon selber gefunden hast / oder es eh schon klar geworden ist - ggf. noch den Code von DelegateCaller posten (möglichst minimal und reproduzierbar).

    Gute 'best practices' und Tips und Beschreibungen diesbzgl. auch hier:

    [Threading in C# - Free E-book]
    http://www.albahari.com/threading/

     


    ciao Frank
    Samstag, 27. November 2010 19:27

Alle Antworten

  • Hallo Smartic

    Join wartet auf das Ende des Thread, was bei dir nicht stattfindet.
    Ich sehe da zwei typische Ursachen, etwa in deinem Code stark anzunehmen: ein klassischer DeadLock, falls DelegateToCaller  gerade mit erstem Thread synchronisiert!

    Oder uU noch (in deinem Code nicht sichtbar), wenn der Thread derweil (direkt+indirekt) in unmanaged Code feststeht, was man bei deiner Aufgabe "asynchron auf eine Hardware"  genauer prüfen sollte.
       (während ein Thread in unmanaged Code, wird dein Abbruch-Flag nicht gepollt?)
    Freitag, 26. November 2010 08:58
  • Hallo Sm.,

    zunächst scheinst Du einen Fehler im Code zu haben. "Thread.Join();" scheint folgendes heissen zu sollen: "_thr.Join();".
    Aber mal angenommen, das wäre schon so, dann ist das Blockieren von "_thr.Join()" ist "by design", es blockiert den aufrufenden Thread, bis ein Thread beendet wird, (während das Standard-COM- und das SendMessage-Pumping fortgesetzt werden).

    Nimmt mal mal vereinfacht im DelegateCaller folgendes an:

       private void DelegateToCaller(string p)
       {
        Thread.Sleep(5000);
       }
    

    dann wartet also "_thr.Join();" natürlich so lange, bis der DelegateToCaller-Thread beendet ist!
    Je nach Inhalt von DelegateToCaller gibt es also vielerlei Möglichkeiten. In Deinem Fall können nun typischerweise Deadlocks und Racebedingungen auftreten. [Empfohlene Vorgehensweise für das verwaltete Threading].

    Insofern - wenn Du es jetzt nicht schon selber gefunden hast / oder es eh schon klar geworden ist - ggf. noch den Code von DelegateCaller posten (möglichst minimal und reproduzierbar).

    Gute 'best practices' und Tips und Beschreibungen diesbzgl. auch hier:

    [Threading in C# - Free E-book]
    http://www.albahari.com/threading/

     


    ciao Frank
    Samstag, 27. November 2010 19:27
  • Hallo Frank & Thomas,

     

    vielen Dank für die zügige Antwort.

     

    Richtig erkannt dass Thread.Join() nicht gehen kann. Aus dem Grund dass dies nur ein konstruiertes Beispiel ist kann so etwas schon vorkommen. :-) In meiner laufenden Version verwende ich tatsächlich _thr.Join() was anderes würde keinen Sinn machen.

     

    Eigentlich sollte ich einigermaßen geimpft sein gegen Deadlocks und ähnliches. Aber wie man sieht ...

    Es ist ein Guter Ansatz den ich an meinem Programm erst einmal nachprüfen muss.

    Wenn ich nichts Finden sollte versuche ich den DelegateCaller genauer zu beschreiben.

     

    Grüße

     

     

    Mittwoch, 1. Dezember 2010 09:09