2013-10-31 19 views
26

Kurze Frage, ich will ein zweites vor eine async Aufgabe ohne Rückgabewert warten starten.
Ist dies der richtige Weg?Verzögerung dann ausführen Aufgabe

Task.Delay(1000) 
    .ContinueWith(t => _mq.Send(message)) 
    .Start(); 

Was passiert mit Ausnahmen?

+0

Warum verwenden Sie das asynchrone CTP? Die endgültige Veröffentlichung ist schon lange nicht mehr möglich. Und wenn Sie eine asynchrone Methode verwenden können, müssen Sie ContinueWith nicht manuell verwenden - warten Sie nur auf die Verzögerung.Könnten Sie bitte mehr Kontext geben? –

+1

Ja, es ist der beste Weg. für die Ausnahmebehandlung: http://stackoverflow.com/questions/12980712/what-is-the-best-way-to-catch-exception-in-task http://stackoverflow.com/questions/5983779/catch-exception-that-is-in-different-thread geworfen – Nahum

+0

@jon: falsches tag :) es wird in einem Windows-Dienst verwendet. – David

Antwort

28

Zunächst funktioniert Start() nur an den (sehr seltenen) Task s, die mit dem Task Konstruktor erstellt wurden (zB new Task(() => _mq.Send(message))). In allen anderen Fällen wird eine Ausnahme ausgelöst, weil Task bereits gestartet ist oder auf einen anderen Task wartet.

Nun, wahrscheinlich der beste Weg, dies zu tun wäre, um den Code in eine separate async Methode zu setzen und verwenden await:

async Task SendWithDelay(Message message) 
{ 
    await Task.Delay(1000); 
    _mq.Send(message); 
} 

Wenn Sie dies tun, eine Ausnahme von der Send() Methode wird am Ende in die zurückgegebenen Task.

Wenn Sie das nicht möchten, ist die Verwendung von ContinueWith() ein sinnvoller Ansatz. In diesem Fall wäre die Ausnahme Task von ContinueWith() zurückgegeben.

Verwenden Sie je nach Typ _mq auch SendAsync(), wenn so etwas verfügbar ist.

0

Sie können alle Ausnahmen beobachten, wenn Sie Wait für die Aufgabe.

Unbehandelte Ausnahmen, die durch Benutzercode geworfen werden, die innerhalb einer Task ausgeführt werden zurück an den Verbindungsfaden, außer in bestimmten Szenarien propagieren, die später in diesem Abschnitt beschrieben werden. Ausnahmen werden weitergegeben, wenn Sie eine der statischen Task Task.Wait oder Task.Wait Methoden verwenden, und Sie behandeln sie, indem Sie den Aufruf in einer try-catch-Anweisung einschließen.

Auszug aus Exception Handling (Task Parallel Library)

Seien Sie vorsichtig mit Timings. Aufgaben verwenden einen Scheduler und werden nicht garantiert gestartet, wenn Sie "go" sagen. Ihr Code wird garantieren mindestens 1000ms Verzögerung nach der Mitteilung an Start, aber es ist nicht garantiert, 1000ms genau zu sein.

6

können Sie jede Ausnahme in der Task geworfen fangen, wenn Sie die Aufgabe Warten zu beenden:

Beachten Sie, dass Ihre Ausnahme in der Task geworfen wird der innere

class Program 
{ 
    static void Main(string[] args) 
    { 
     try 
     { 
      Task task = Task.Delay(1000) 
       .ContinueWith(t => Program.throwsException()); 

      task.Wait();  
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine("Exception:" + ex.Message); // Outputs: Exception:One or more errors occurred. 
      Console.WriteLine("Inner exception:" + ex.InnerException.Message); // Outputs: Exception:thrown 
     } 
     Console.ReadKey(); 

    } 
    static void throwsException() 
    { 
     Console.WriteLine("Method started"); 
     throw new Exception("thrown"); 
    } 
} 
sein
Verwandte Themen