2013-07-16 7 views
16

Ich verwende eine Bibliothek, die Methoden mit der Endung ...Async bereitstellt und Task zurückgibt. Ich werde diese in einer Befehlszeilenanwendung verwenden. Also muss ich sie viel synchron nennen.Warten auf asynchrone Task ohne Wrapping von Ausnahmen in AggregateException

C# natürlich erlaubt nicht diese Methoden in Main Methode aufrufen, da Sie async Modifikator auf Main Methode verwenden können. Angenommen, das ist die Aufgabe:

var task = datastore.Save(data); 

ich mehrere Lösungen wie gefunden:

Tasks.WaitAll(task); 
task.Wait(); 

jedoch alle diese einwickeln geworfen Ausnahmen in AggregateException, Ich will nicht, dass. Ich möchte nur sagen task.Result und ich erwarte, dass die ursprüngliche Ausnahme ausgelöst wird.

Wenn ich eine Methode Task<TResult> zurückgeben, task.Result wirft AggregateException, obwohl keine Fortsetzung Aufgaben festgelegt sind. Warum ist das Hacken?

Ich habe auch versucht,

task.RunSynchronously(); 

es gibt Fehler:

RunSynchronously may not be called on a task not bound to a delegate, such as the task returned from an asynchronous method.

also denke ich, das ist nicht für Methoden wie async markiert.

Haben Sie Ideen zu Mustern, die Bibliotheken verwenden, die für asynchrone Anwendungen in Konsolenanwendungen entwickelt wurden, in denen kein asynchroner Kontext vorhanden ist?

Antwort

27

I am going to use these in a command line application. So I need to call them synchronously a lot.

Nein, Sie nicht. Sie könnenasync - await in einer Konsolenanwendung verwenden, müssen Sie nur eine asynchrone Synchronisierung Übergang ganz oben machen. Und Sie können das zu tun, indem Wait() mit:

public static void Main() 
{ 
    MainAsync().Wait(); 
} 

public static async Task MainAsync() 
{ 
    var datastore = …; 
    await datastore.SaveAsync(); 
} 

Normalerweise kombiniert await mit Wait() ist eine schlechte Idee (es kann Deadlocks verursachen), aber es ist die richtige Lösung.

Beachten Sie, dass wenn SaveAsync() eine Ausnahme auslöst und Sie es nicht fangen, wird es als AggregateException von der Wait() rethrown. Aber Sie können es als die ursprüngliche Ausnahme in MainAsync() fangen (weil es Wait() nicht verwendet).

Wenn Sie wirklich die erste Ausnahme direkt geworfen haben wollten, könnten Sie etwas ähnliches tun, was await tut: task.GetAwaiter().GetResult(). Beachten Sie, dass wenn die Task mehr als eine Ausnahme enthält, Sie nur die erste erhalten (aber das gleiche gilt für await).

When I use a method returning Task<TResult> , task.Result throws AggregateException even though there are no continuation tasks set. Why is this happening?

Dies hat nichts mit Fortsetzungen zu tun. Eine einzelne Task kann mehrere Operationen darstellen, von denen jede eine Ausnahme auslösen kann. Aus diesem Grund Task Methoden immer werfen die Ausnahmen in einem AggregateException verpackt.

I also have tried task.RunSynchronously()

Das macht keinen Sinn. RunSynchronously() kann nur für Task s verwendet werden, die mit dem Task Konstruktor erstellt wurden. Das ist hier nicht der Fall, also kannst du es nicht benutzen. Task s, die von asynchronen Methoden zurückgegeben werden, sind immer bereits gestartet.

2

können Sie erstellen eine Dummy-Main

public static void Main() 
{ 
    MainAsync().Wait(); 
} 

public static async Task MainAsync() 
{ 
    try { 
     var result = await dataStore.Save(data); 
    } catch(ExceptionYouWantToCatch e) { 
     // handle it 
    } 
} 

Auch hierzu finden Sie diese Antwort: https://stackoverflow.com/a/9212343/1529246

Verwandte Themen