2015-01-13 9 views
7

Ich bin nicht sicher, ob dies möglich ist, mich hier so aus:Passing eine Aufgabe als Parameter

Ich habe eine Abfolge von Aktion mehr

async Task MethodA(...) 
{ 
    // some code 
    // a call to specific Async IO bound method 
    // some code 
} 

gibt es auch MethodB(), MethodC() usw. ausführen , und alle haben genau denselben Code, mit Ausnahme des Aufrufs für bestimmte Async IO-gebundene Methode. Ich versuche einen Weg zu finden, einen Aufgabenzeiger an eine Methode zu übergeben, damit wir sie später in einer Method() ausführen können.

Was ich derzeit tue, ist dies:

private async Task Method(Func<Task<Entity>> func) 
{ 
    // some code 
    var a = await task.Run(func); 
    // some code 
} 

var task = async() => await CallToIOBoundTask(params); 
Method(task); 

Dieser Code jedoch jedes Mal einen neuen Thread zieht, die nicht für IO gebunden Aufgabe erforderlich ist, und sollte vermieden werden.

Gibt es also eine Möglichkeit, den Code so zu refactorisieren, dass kein ThreadPool-Thread verwendet wird? Ein Ziel ist es, einen Code wie folgt zu haben:

Es ist auch wichtig zu erwähnen, dass verschiedene IO-Aufrufe verschiedene Methodensignaturen haben. Außerdem kann eine Task nur in Method() Körper ausgeführt werden, und nicht vorher.

+0

Möchten Sie warten, bis die Anweisung in der Methode 'Method()' für die asynchrone Task beginnt? Wenn dies der Fall ist, ist Ihr Codebeispiel in der Frage falsch (Sie warten auf eine _existierende_ Aufgabe, anstatt eine Aufgabe zu erstellen), und die bereits bereitgestellte Antwort entspricht Ihren Wünschen. Wenn Sie jedoch nur eine Aufgabe abwarten möchten, die Sie vor dem Aufruf der 'Method()' -Methode gestartet haben, beachten Sie, dass Sie dies leicht tun können: Rufen Sie einfach z. Übergeben Sie den Rückgabewert eines Aufrufs an CallToIOBoundTask() als Argument für den Aufruf der Method() -Methode. –

+0

@PeterDuniho Eine Antwort auf Ihre Frage befindet sich im letzten Satz der Frage - Aufgabe muss ihre Ausführung in method() starten. – Goran

Antwort

16

Natürlich, rufen Sie einfach die func, erhält eine Aufgabe zurück, und await es:

async Task Method(Func<Task<Entity>> func) 
{ 
    // some code 
    var a = await func(); 
    // some code 
} 

Auch wenn Sie, dass Lambda-Ausdruck senden, da alle es ist eine async Aufruf der Methode zu tun, die in selbst eine Aufgabe gibt, braucht es nicht async an sich zu sein:

Method(() => CallToIOBoundTask(params)); 

, die so lange in Ordnung, da alle diese Anrufe Task<Entity> zurück. Wenn nicht, können Sie nur Task verwenden (was bedeutet, dass der Vorgang gestartet und auf seinen Abschluss gewartet wird) und Sie können das Ergebnis nicht verwenden.

+0

Heh, ich habe es ohne Klammern versucht, und es hat nicht funktioniert. :) AS für deinen zweiten Vorschlag, was wird die IL für diesen Teil generieren:() => CallToIOBoundTask (params)? Wird das eine asynchrone Aufgabenmethode sein oder nicht? Ich kann diesen Code nicht als ungültig generieren lassen. – Goran

+0

@Goran Es wird keine asynchrone Methode sein. Aber es wird eine Aufgabe zurückgeben, da 'CallToIOBoundTask' eine Aufgabe zurückgibt. Es kann auch nicht void sein, da der Parameter kein 'Action' ist, sondern' Func > '. Wenn Sie sicherstellen möchten, dass Sie dieses Lambda auf '() => {return CallToIOBoundTask (params); } 'Das ist genau das Gleiche. – i3arnon