2009-06-09 7 views
2

Mit dem Code zu lösen, ich einen eigenen Threadpool umgesetzt: http://www.developer.com/net/article.php/3783756Wie dieses spezielle Threading-Problem aus dem folgenden Artikel

Dies ist, was ich erreichen möchte: durch einen Timer ausgelöst, sollte ein Dienst eine Datenbank abfragen alle 5 Sekunden für die Ausführung neuer Jobs. Ein Job ist im Grunde nur die Information über ein Kommandozeilenprogramm, das mit Argumenten ausgeführt werden muss.

Bis zu 50 oder mehr dieser Programme sollten gleichzeitig ausgeführt werden können. Ein Programm kann ein paar Sekunden, Minuten und auch Stunden dauern. Der Dienst muss zu jeder Zeit die Kontrolle über diese Programme haben, d. H. Er muss in der Lage sein, auf Anforderung zum Beispiel ein Programm zu beenden.

Mit der ThreadPool-Implementierung von oben begann ich, die auszuführenden Programme in die Warteschlange zu stellen und konnte sehen, wann der Dienst sie tatsächlich ausführte. Kein Problem bis jetzt. Der Mechanismus funktioniert hier jedoch wie folgt:

Der ThreadPool erstellt einen Arbeitsfaden und startet ihn. Immer wenn ein Programm in die Warteschlange gestellt wird, merkt dies der Werkerthread und ruft einen Delegaten auf, der im Wesentlichen ein System.Diagnostics.Process-Objekt instanziiert und das externe Programm startet. Der Thread ist dann mit seiner Arbeit fertig und könnte weitere Programme starten. Wenn jedoch kein Programm gestartet wird, veranlasst ein Leerlauftimer den Threadmanager, den Thread zu beenden und somit den gestarteten Prozess zu unterbrechen.

Das ist nicht was ich brauche. Hat jemand hier eine Idee, wie man mit dem beschriebenen Szenario besser umgeht?

Antwort

3

1) Warum ist der Tod eines Fadens in diesem Prozess der Tod des anderen, gestarteten Prozesses? Wenn Sie diese Frage beantworten, haben Sie Ihr Problem gelöst.

2) Das sieht aus wie ein ziemlich mieser und ziemlich naiv, ThreadPool Artikel. Überprüfen Sie die Joe Duffy's Serie in einem benutzerdefinierten Threadpool (part 1, part 2 und part 3). Code wie dieser ist überraschend kompliziert und eine erhebliche Wartungslast für sich.

3) (Die wirkliche Antwort) Warum verwenden Sie überhaupt einen Threadpool? Dein Threadpool verwendet immer nur einen Thread auf einmal, warum nicht einfach einen Timer verwenden und deinen Haupt-Thread auslösen? Führt Ihre App auch andere Dinge in einer Benutzeroberfläche aus, die Sie reaktiv halten müssen?

Sie sich von der Thread befreien, gibt es keine Notwendigkeit, es ist Ihnen das Leben schwer zu machen und threadpools im Allgemeinen nicht hosten lang laufende Aufgaben konzipiert. Dafür sind einzelne Threads gedacht. Wenn Sie den Timer in einem separaten Thread auslösen müssen, erstellen Sie einfach einen Thread, um damit umzugehen, und verwenden Sie diesen einen identischen Thread, um all Ihre Prozesse zu generieren. Sie können dann Ihren Prozessstatus an einem zentralen, sinnvollen Ort verfolgen. :)

+0

Hm. Es war eigentlich eine Anfrage des Kunden, mit Threads zu arbeiten (was er auch getan hat und jetzt von uns in .NET möchte). Nun, da ich einige Erfahrungen mit dieser "lausigen" Threadpool-Implementierung gemacht habe, ist mir aufgefallen, dass es keinen Sinn ergibt. Da das Starten eines externen Programms bereits neue Threads erzeugt, die parallel ausgeführt werden. Es scheint wirklich so, als ob eine Sammlung, die die Prozesse verwaltet, sich richtig anfühlt ... – Mephisztoe

1

Sind Sie sicher, dass ein Thread-Pool der optimale Weg ist, um dies zu behandeln? einen neuen Thread Laichen für jeden Prozess, der meist im Leerlauf sein wird, aber vorhanden sein muss, bis der Prozess scheint mir wie eine Verschwendung von einem Thread beendet.

Ich würde dies alles mit einem einzigen Thread und einem Wörterbuch von Prozessen implementieren. Der Thread fragt regelmäßig die Datenbank und alle Prozesse ab, um zu sehen, welche Aktionen ausgeführt werden müssen.

+0

Sie haben recht, ... es könnte sinnvoll sein, stattdessen mit einer Sammlung zu arbeiten. – Mephisztoe

0

AFAIK, Prozesse, die von Process.Start erzeugt werden, werden auch dann ausgeführt, wenn der Thread Process.Start beendet wird. Der folgende Code veranschaulicht dies. LongRunningApp.exe läuft weiter, nachdem das Hauptprogramm beendet wurde:

static void Main(string[] args) 
{ 
    Process p = new Process(); 
    ProcessStartInfo psi = new ProcessStartInfo(@"C:\LongRunningApp.exe"); 
    psi.CreateNoWindow = true; 
    psi.UseShellExecute = false; 
    p.StartInfo = psi; 
    p.Start(); 
    Console.ReadLine(); 
} 
Verwandte Themen