2016-06-17 1 views
1

Dies ist die Aufgabe, bei der die Ausnahme ausgelöst wird.Übergeben der Ausnahme von Task.Run, um ordnungsgemäß zu warten, und Debugger

public Task<SensorReading> ReadSensorsAsync(int cell) 
{ 
    return Task.Run(() => { 
      throw new ArgumentNullException(); 
... 

Dies ist die async Methode:

private async void TimerCallback(object state) 
{ 
    try 
    { 
     var tasksRead = Enumerable.Range(3, 35).Select(i => sensorReader.ReadSensorsAsync(i)).ToList(); 
     await Task.WhenAll(tasksRead); 
     var r = tasksRead.Select(x => x.Result).ToList(); 
     var taskRecordREsult = RecordReadingAsync(r).Result; 
    } 
    catch(Exception e) 
    { 
     // expecting to catch everything here 
    } 
} 

Was ich erwartet hatte, dass Ausnahme in await Teil des Codes behandelt werden würde. Allerdings bekomme ich in Visual Studio-Debugger eine unbehandelte Ausnahme.

Frage - wie alle Art von Ausnahme von Task.Run zum erwarteten Teil richtig übergeben?

+0

Wenn Sie auf „Weiter“ getroffen, es hat * dann * erwischt? Das habe ich sehr oft gesehen ... –

+0

BTW können Sie den Ausdruck "erwarten" in das Beispiel aufnehmen? – alexm

+0

@JonSkeet: Ja, "weiter" bringt mich zum Warten, aber ich möchte nicht, dass VS mir sagt, dass ich jedes Mal, wenn etwas in "Task.Run" passiert, eine "unbehandelte Ausnahme" habe. – Pablo

Antwort

0

Eine mögliche Lösung besteht darin, Ihr Task.Run-Lambda in eine eigenständige Methode zu extrahieren und das Attribut [DebuggerStepThrough] hinzuzufügen. In der Theorie (ich habe dies nicht getestet), wird dies die erste Ausnahme im Debugger unterdrücken und es später abfangen. Es ist nicht schön, aber es sollte den Trick machen.

+0

Das Problem ist nicht nur Debugger selbst, sondern auch die Behandlung tiefer Ausnahmen.Die erste Frage bleibt also - ist es die richtige Art, alle in Task.Run aufgetretenen Ausnahmen zu behandeln. – Pablo

+0

In .NET 4.0 müssen Ausnahmen, die in Task.Run ausgelöst wurden, behandelt oder zumindest beobachtet werden. Zwei Hauptmuster sind, entweder einen "Try..Catch" Block in die Task.Run zu setzen, oder das Ergebnis des Laufs durch Überprüfen von 'Task.IsFaulted' zu prüfen (wie in einem' .ContinueWith() 'Block). In .NET 4.5 ermöglicht das Verwenden des Wartens, dass Ausnahmen ordnungsgemäß zum ursprünglichen Thread zurückgebracht werden. – MCattle

+0

In einem Fall, in dem Sie eine Task.Run für eine Prozedur starten, die kein Ergebnis zurückgibt, kann eine unbehandelte Ausnahme in der Task die gesamte Anwendung (zumindest in Windows Forms) aufgrund von Exceptions herunterfahren dürfen nicht in Hintergrundthreads behandelt werden. – MCattle

0

dieses Programm versuchen und sehen, ob Sie noch zu brechen bekommen ..

seine Arbeits für mich

class Program 
{ 
    static void Main(string[] args) 
    { 
     new Program().TimerCallback(); 
    } 

    public Task<string> ReadSensorsAsync(string cell) 
    { 
     return Task.Run(() => 
     { 
      if(cell == null) throw new ArgumentNullException(); 
      return cell; 
     }); 
    } 

    public Task<string> RecordReadingAsync(IEnumerable<string> cell) 
    { 
     return Task.Run(() => 
     { 
      return string.Join(",", cell); 
     }); 
    } 

    public async void TimerCallback() 
    { 
     try 
     { 
      var tasksRead = new string[] { "1", null, "3" }.Select(s => ReadSensorsAsync(s)); 
      var taskRecordResult = await RecordReadingAsync(await Task.WhenAll(tasksRead)); 
      Debugger.Log(1, "test", taskRecordResult); 
     } 
     catch (Exception e) 
     { 
      //catches here 
      Debugger.Log(1, "test", e.Message ?? e.ToString()); 
     } 
    } 
} 
Verwandte Themen