2017-05-18 3 views
3
nicht

Ich versuche, eine von mehreren Aufgaben neu zu starten, wenn es fehlschlägt. Ich benutze .ContinueWith(t => { HandleException(t); }, TaskContinuationOptions.OnlyOnFaulted); wo die HandleException(t) Methode sollte die Aufgabe in dem Array von bestehenden Aufgaben und erstellen Sie eine neue an ihrer Stelle. Nur die Aufgabe, die an meine HandleException(t)-Methode übergeben wurde, unterscheidet sich von der ursprünglichen Aufgabe, so dass ich sie in meinen bestehenden Aufgaben nicht finden kann. Auch die bestehende Aufgabe läuft zum Zeitpunkt der Ausnahme noch.Neustarten Aufgabe, wenn es

Beispiel:

using System; 
using System.Threading.Tasks; 
using System.Threading; 

static Task[] tasks; 
static void Main(string[] args) 
{ 
    tasks = new Task[2]; 
    for (int i = 0; i < tasks.Count(); i++) 
    { 
     tasks[i] = Task.Run(() => { Thread.Sleep(1000); throw new Exception("BOOM"); }) 
      .ContinueWith(t => { HandleException(t); } 
      , TaskContinuationOptions.OnlyOnFaulted); 

     Console.WriteLine(String.Format("Task {0} started", tasks[i].Id)); 
    } 

    Console.ReadLine(); 
} 

static void HandleException(Task task) 
{ 
    Console.WriteLine(String.Format("Task {0} stopped", task.Id)); 

    // Check task status 
    for (int i = 0; i < tasks.Count(); i++) 
    { 
     Console.WriteLine(String.Format("Task {0} status = {1}", i, tasks[i].Status)); 
    } 
    // fFind and restart the task here 
    if (tasks.Contains(task)) 
    { 
     int index = Array.IndexOf(tasks, task); 
     tasks[index] = Task.Run(() => { Thread.Sleep(1000); throw new Exception("BOOM"); }) 
     .ContinueWith(t => { HandleException(t); } 
     , TaskContinuationOptions.OnlyOnFaulted); 

     Console.WriteLine(String.Format("Task {0} started", tasks[index].Id)); 
    } 
} 

Meine Anwendung ergibt:

Task 3 started 
Task 6 started 
Task 5 stopped 
Task 0 status = Running 
Task 2 stopped 
Task 1 status = Running 
Task 0 status = Running 
Task 1 status = Running 

Da die an die HandleException(t) weitergegeben Aufgabe von der ursprünglichen Aufgabe unterschiedlich ist, wird es nicht in den tasks[] gefunden und somit nicht neu gestartet. Betrachtet man auch die Zustände der tasks[] ist es noch nicht gestoppt. Wie kann ich meine Aufgabe ordnungsgemäß neu starten?

Antwort

4

Das ist, weil Sie Fortsetzung Aufgabe in Ihrem Array speichern, nicht originäre Aufgabe (das ist - Sie speichern Ergebnis ContinueWith). Um das Problem zu beheben, speichern Sie die ursprüngliche Aufgabe stattdessen:

var task = Task.Run(() => { Thread.Sleep(1000); throw new Exception("BOOM");}); 
task.ContinueWith(t => { HandleException(t); } 
     , TaskContinuationOptions.OnlyOnFaulted); 
tasks[i] = task; 
+0

Ehrfürchtig, das war in der Tat das Problem. Es hat auch den Aufgabenstatus behoben. – MrEighteen

+0

@Evk Da HandleException (t) ein rekursiver Aufruf ist, führt das nicht zu einem Stack-Überlauf? –

+1

@MaximPodkolzin nein, weil alles auf verschiedenen Threads passiert. Neue Aufgabe wird über 'Task.Run' gestartet, dies ruft einen Thread aus dem Thread-Pool ab> Ausnahme wird ausgelöst> HandleException wird aufgerufen, möglicherweise erneut in einem anderen Thread>' Task.Run' wird erneut aufgerufen und ein anderer Thread wird aus dem Thread-Pool abgerufen (das selbe kann nicht verwendet werden, da es mit der Ausführung von HandleException beschäftigt ist.> Der aktuelle Thread beendet die Ausführung und kehrt zum Pool zurück. Für einen Stack-Überlauf sollte derselbe Thread die Funktion rekursiv ausführen, aber hier haben wir verschiedene Threads (und damit verschiedene Stacks). – Evk

Verwandte Themen