2014-05-16 11 views
6

Ich möchte folgendes schreiben:Task-Rückgabewert, ohne Aufgabe <T> (async/erwarten Muster)

public string GetSomeValue() 
{ 
    //directly return the value of the Method 'DoSomeHeavyWork'... 
    var t = DoSomeHeavyWork(); 
    return t.Result; 
} 

public Task<string> DoSomeHeavyWork() 
{ 
    return Task.Run(() => { 
     // do some long working progress and return a string 
     return "Hello World!"; 
    }); 
} 

Wie Sie das Ergebnis aus der DoSomeHeavyWork() zurückkehren sehen kann ich die Task.Result Eigenschaft verwendet haben , was in Ordnung ist, aber nach Untersuchungen wird dies den Thread blockieren.

Ich würde gerne das async/erwarten Muster dafür verwenden, aber kann nicht finden, wie dies zu tun ist. Wenn ich das gleiche mit Asynchron/erwarten mit meinem aktuellen Wissen tat ich immer mit diesem Ende:

public async Task<string> GetSomeValue() 
{ 
    //directly return the value of the Method 'DoSomeHeavyWork'... 
    var t = DoSomeHeavyWork(); 
    return await t; 
} 

public Task<string> DoSomeHeavyWork() 
{ 
    return Task.Run(() => { 
     // do some long working progress and return a string 
     return "Hello World!"; 
    }); 
} 

Diese Lösung muß nicht ganz meine Bedürfnisse passen, weil ich nur die Zeichenfolge zurückgeben möchten und kein Task<string>, wie Kann dies mit async erreicht werden?

+0

Warum kann man nicht zurückgeben 'Aufgabe ' denn wenn man 'es await' es gibt einen' string'. Willst du das nicht? – Enigmativity

Antwort

10

Sie können nicht.

Der gesamte Punkt von async ist Code asynchron. Der Code gibt also einen Versprechen eines zukünftigen string Wert zurück, der in .NET als Task<string> dargestellt wird.

Denken Sie es so: Wenn Ihr Code public string GetSomeValue() ruft, dann durch die Zeit, die Methode zurückgibt, Sie bereits ein string haben. Dies ist per Definition synchron.

In Ihrem Beispiel haben Sie "schwere" Arbeit, die ich interpretiere "CPU-gebunden". In diesem Fall, nur die Arbeit synchron tun:

public string DoSomeHeavyWork() 
{ 
    // do some long working progress and return a string 
    return "Hello World!"; 
} 

Im Allgemeinen sollten APIs nicht "liegen"; Wenn sie synchron sind, sollten sie eine synchrone Signatur (nicht Task) haben.

Bearbeiten: Laut Ihrem Kommentar ist die "schwere" Arbeit ein WCF-Aufruf, der I/O-gebunden ist, nicht CPU-gebunden.

In diesem Fall ist die Arbeit natürlich asynchron. Verwenden Sie asynchrone WCF Methoden (nicht Task.Run), und lassen Sie die Asynchronität durch Ihre Codebasis wachsen:

public async Task<string> GetSomeValueAsync() 
{ 
    //directly return the value of the Method 'DoSomeHeavyWork'... 
    var t = DoSomeHeavyWorkAsync(); 
    return await t; 
} 

public async Task<string> DoSomeHeavyWorkAsync() 
{ 
    // Call asynchronous WCF client. 
    await ...; 
    return "Hello World!"; 
} 
+0

Wie würden Sie mein Problem mit der Eigenschaft "Task.Result" lösen oder wissen Sie etwas Besseres? (Würde mich über Code-Snippets freuen, wenn Sie eine bessere Alternative kennen) –

+0

In meinem realen Live-Beispiel rufe ich eine WCF-Anfrage an einen Client an und wollte eine Methode, die async ausführt, um den Client nicht zu blockieren, während der Server die Methode aufruft (beide Server/Client sind WPF) sollte ich dann das Task-Objekt anstelle der aufgelösten String/Objekt? –

+0

Ich habe meine Antwort mit meiner bevorzugten Lösung bearbeitet: Mach einfach die Arbeit direkt. Und ich habe es wieder bearbeitet, da die "schwere" Arbeit eine WCF-Anfrage ist. –

Verwandte Themen