Laden...

Thread TimeOut

Erstellt von mike.net vor 15 Jahren Letzter Beitrag vor 15 Jahren 4.142 Views
M
mike.net Themenstarter:in
9 Beiträge seit 2009
vor 15 Jahren
Thread TimeOut

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

Gelöschter Account
vor 15 Jahren

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.

3.971 Beiträge seit 2006
vor 15 Jahren
Thread TimeOut

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...

Gelöschter Account
vor 15 Jahren

prinzipiell halte ich diese implementierung für ein gutes beispiel für "sterbende threads"

3.971 Beiträge seit 2006
vor 15 Jahren

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...

M
mike.net Themenstarter:in
9 Beiträge seit 2009
vor 15 Jahren

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) 😉

49.485 Beiträge seit 2005
vor 15 Jahren

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

3.971 Beiträge seit 2006
vor 15 Jahren

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...

49.485 Beiträge seit 2005
vor 15 Jahren

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

3.971 Beiträge seit 2006
vor 15 Jahren

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...

360 Beiträge seit 2005
vor 15 Jahren

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 😃

3.971 Beiträge seit 2006
vor 15 Jahren

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.

  • Da oben in dem Beispiel auch kein Join enthalten war, noch eins eingebaut.
  • ManualResetEvent entfernt, wird in diesem Beispiel nicht gebraucht.
  • Abort hinzugefügt

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...