Ich arbeite an einer Legacy-Anwendung, die auf NET 3.5 aufbaut. Dies ist eine Einschränkung, die ich nicht ändern kann. Ich muss einen zweiten Thread ausführen, um eine lange laufende Aufgabe auszuführen, ohne die Benutzeroberfläche zu sperren. Wenn der Thread abgeschlossen ist, muss ich irgendwie einen Rückruf ausführen.
Im Moment habe ich diesen Pseudocode ausprobiert:
%Vor%Die zweite Option, die die Benutzeroberfläche nicht sperrt, ist die folgende:
%Vor%Natürlich ist die zweite Lösung nicht gut, weil sie die Benutzeroberfläche überlädt. Was ist der richtige Weg, um einen Rückruf auszuführen, wenn ein _thread abgeschlossen ist? Woher weiß ich auch, ob der Thread abgebrochen oder abgebrochen wurde?
* Hinweis: * Ich kann den BackgroundWorker nicht verwenden und ich kann die Async-Bibliothek nicht verwenden. Ich muss mit der nativen Thread-Klasse arbeiten.
Der einfachste Ansatz besteht darin, grundsätzlich einen Rückruf hinzuzufügen. Sie können dies sogar einfach so durchführen, wie Multicast-Delegierte funktionieren:
%Vor% Das ist sehr Vanille, und der Rückruf wird nicht ausgelöst, wenn der Thread abgebrochen wird oder eine Ausnahme auslöst. Man kann es in einer Klasse einpacken mit entweder mehr Rückrufen, oder einem Rückruf, die den Status angibt (abgebrochen, hat eine Ausnahme etc.) und Griffe, die durch den ursprünglichen Delegaten Einwickeln, es in einem Verfahren mit einem Aufruf try
/ catch
blockiert und führt den Rückruf entsprechend aus.
Sofern Sie keine besonderen Maßnahmen ergreifen, wird der Callback im Hintergrundthread ausgeführt , so dass Sie Control.BeginInvoke
(oder was auch immer) verwenden müssen, um zum UI-Thread zurückzukehren.
Ich verstehe Ihre Anforderungen absolut, aber Sie haben eine entscheidende Sache übersehen: Müssen Sie wirklich synchron auf das Ende dieses Threads warten? Oder müssen Sie nur den "Finalizer" ausführen, nachdem das Ende des Threads erkannt wurde?
Im letzteren Fall einfach den Aufruf von myLongRunningTask
in eine andere Methode einfügen:
und benutze es als Routine des Threads. Auf diese Weise wissen Sie, dass die Finalisierung bei den Threads und unmittelbar nach dem Ende des eigentlichen Jobs erfolgt.
Wenn Sie jedoch mit einer UI oder anderen Schedulern arbeiten, wird die "Finalisierung" nun auf Ihrem Thread und nicht auf den "normalen Threads" Ihres UI- oder Kommunikationsframeworks ausgeführt . Sie müssen sicherstellen, dass alle Ressourcen außerhalb Ihres Thread-Tasks ordnungsgemäß geschützt oder synchronisiert sind, sonst werden Sie wahrscheinlich mit anderen Anwendungsthreads kollidieren.
Wenn Sie beispielsweise in WinForms irgendwelche UI-Elemente aus dem Finalizer berühren, benötigen Sie Control.InvokeRequired (securely = true) und Control.BeginInvoke / Invoke, um den Kontext zurück zum UI-Thread zu hüpfen.
>In WPF benötigen Sie beispielsweise den Dispatcher.BeginInvoke, bevor Sie irgendwelche Elemente der Benutzeroberfläche aus dem Finalizer berühren.
Oder, falls der Konflikt mit irgendwelchen von Ihnen kontrollierten Threads auftreten könnte, könnte das einfache richtige lock()
genügen. usw.
Vielleicht mit Bedingungsvariablen und Mutex, oder einige Funktionen wie wait (), signal (), möglicherweise gewartet wait (), um den Hauptfaden nicht unendlich zu blockieren.
In C # ist dies:
%Vor%mehr dazu hier: Bedingungsvariablen C # /. NET
Es ist das Konzept des Monitor-Objekts in C #, Sie haben auch eine Version, die es ermöglicht, das Zeitlimit zu setzen
%Vor%mehr dazu hier: Ссылка
Tags und Links c# multithreading