Hi,
gibt es für folgendes Vorhaben eine Lösung?:
Ich möchte einen neuen Thread starten, dieser Thread soll maximal 30 Sek. laufen, wenn er die 30 Sek. überschreitet soll ein Event gefeuert werden, der den Thread abbricht und irgendwas anderes macht...
Nach was muss ich suchen, was sind die Stichworte?
Danke!
Grüsse
class MyAsyncOperation {
private ManualResetEvent m_wh = new ManualResetEvent(false);
private volatile bool m_abort = false;
public void Start() {
m_wh.Reset();
ThreadPool.QueueUserWorkItem(Start_Impl, null);
ThreadPool.RegisterWaitForSingleObject(m_wh, TimeOut, null, 10000, true); //10 Sekunden warten.
}
private void Start_Impl(object state) {
try {
while (!m_abort) {
//Aufgaben durchführen.
}
}
finally {
m_wh.Set();
}
}
private void TimeOut(object state) {
m_abort = true;
}
public void Join() {
m_wh.WaitOne();
}
}
Zum Starten erstellst du eine neue Instanz der Klasse und rufst anschließend Start auf. Die Funktion Start bricht sich dann automatisch nach spätestens 10 Sekunden ab. Zum Abbrechen selbst könntest du auch Thread.Abort() verwenden, wenn du zuvor den Thread manuell erstellt hast
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
Was ist bei dir ein "sterbende Thread"?
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
benutze einen timer der vom thread gestartet wird. setze das intervall auf 30 sekunden und im eventhandler der nach ablauf des intervalles aufgerufen wird, vernichtest du den thread.
Danke! Das war auch mein 1. Ansatz, aber ich dachte es geht auch eleganter 😃
Was ist bei dir ein "sterbende Thread"?
Er meint wahrscheinlich, dass sich der TE dein Code 'klaut' und sich nicht mehr meldet (anstatt sich die Lösung selbst zu erarbeiten) 😉
Hallo kleines_eichhoernchen,
Was ist bei dir ein "sterbende Thread"?
ich vermute JAck30lena meint, dass deine Implementierung so gut ist, dass man sie als Standardimplementierung für abzubrechende Thread verwenden kann.
Mal abgesehen davon, dass es in TimeOut wohl m_abort = true;
heißen müsste, verstehe ich nicht, wozu das lock in TimeOut und Start_Impl gut ist. Ich denke, es geht auch ohne.
herbivore
dass es in TimeOut wohl m_abort = true; heißen müsste
ist geändert.
verstehe ich nicht, wozu das lock in TimeOut und Start_Impl gut ist. Ich denke, es geht auch ohne
Auf Einkern CPUs könnte man das lock weglassen, ohne lock wäre das ganze so gar performanter. Bei mehreren CPU-Kernen wird beim zuweisen einer Variable erst nur der Wert im jeweiligen CPU-Cache geändert, nicht aber im Arbeitsspeicher oder den Caches der jeweiligen anderen CPU-Kernen. Eine Synchronisierung zwischen Cache->Arbeitsspeicher->Cache findet nicht sofort statt, sondern kann sich je nach CPU unterscheiden.
In diesen Beispiel könnte man aber auch statt lock volatile oder Thread.MemoryBarrier() verwenden, welches jeweils eine Cache-Synchronisation erzwingt.
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
Hallo kleines_eichhoernchen,
Eine Synchronisierung zwischen Cache->Arbeitsspeicher->Cache findet nicht sofort statt, sondern kann sich je nach CPU unterscheiden.
Ja, das ist schon klar. Aber es kann doch sowieso immer sein, dass das m_abort = true;
einen kleinen Moment zu spät kommt und daher der Thread noch einen weiteren Schleifendurchlauf macht bis er merkt, dass er sich eigentlich beenden soll. Daran ändert auch das lock nicht. Und da du selbst sagst, dass lock Performance kostet, kann man es auch einfach weglassen. Ich könnte mir höchstens vorstellen, dass man die m_abort volatile machen müsse, aber nicht dass man lock braucht.
herbivore
So hab jetzt das lock durch volatile ersetzt. In dieser kleinen Klasse ist es aus Performance-Sicht doch besser auf lock zu verzichten.
Allerdings ohne lock, volatile,Memory Barrier oder anderen Threadsynchronisation sollte man seine Anwendung nicht Multithreaded entwickeln, da es auf Itanium-Systemen keine Cache-Coherency gibt und man dadurch für aktuelle Werte im jeweiligen CPU-Cache selbstverantwortlich ist.
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
Moin,
angeregt durch klein eichhörnchens Antwort auf meine Frage im Thread Asynchrones Ausführen mit Timeout bin ich auf den oben genannten Code-Schnipsel gestoßen.
Dazu habe ich noch eine Frage. Der von mir aufgerufene Thread ruft genau eine Methode auf - und die kehrt im ungünstigsten Fall (weswegen ich den Zirkus überhaupt veranstalte) nicht zurück. Daher muss ich den Thread in diesem Fall beenden. Da der Thread aber keine Schleife enthält nützt mir eine von außen gesetzte Abbruchbedingung nichts. Kommt man irgendwie an den Thread ran um ihn mit Abort zu terminieren?
Gruß,
Markus 😃
Auch wenn du die Möglichkeit hast/hättest an den entsprechenden Thread aus dem ThreadPool heranzukommen, niemals Abort aufrufen, die CLR würde die komplette AppDomain killen.
class MyAsyncOperation {
private Thread m_thread;
public void Start() {
m_thread = new Thread(Start_impl);
m_thread.IsBackground = true;
m_thread.Start();
ThreadPool.RegisterWaitForSingleObject(m_wh, TimeOut, null, 10000, true); //10 Sekunden warten.
}
private void Start_Impl(object state) {
try {
//
//DoSomething
//
}
finally {
//Aufräumen
}
}
private void TimeOut(object state) {
m_thread.Abort();
}
public void Join() {
m_thread.Join();
}
public void Abort() {
m_thread.Abort();
}
}
Du kannst natürlich auch hier eine eigene ThreadPool-Implementierung mit eigenen Threads verwenden.
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...