2012-09-14 4 views
5

Für den laufenden Code asynchron (zB mit async/warten) brauche ich eine ordnungsgemäße Aufgabe. Natürlich gibt es im Framework mehrere vordefinierte Methoden, die die häufigsten Operationen abdecken, aber manchmal möchte ich meine eigenen schreiben. Ich bin neu in C#, also ist es gut möglich, dass ich es falsch mache, aber ich bin zumindest nicht ganz glücklich mit meiner derzeitigen Praxis. Siehe das folgende Beispiel für das, was ich tue:Wie schreibe ich eine benutzerdefinierte Aufgabe richtig zurückgeben Methode

public async Task<bool> doHeavyWork() 
    { 
     var b1 = await this.Foo(); 
     //var b2 = await Task<bool>.Factory.StartNew(Bar); //using Task.Run 
     var b2 = await Task.Run(()=>Bar()); 
     return b1 & b2; 
    } 

public Task<bool> Foo() 
    { 
     return Task.Factory.StartNew(() => 
            { 
             //do a lot of work without awaiting 
             //any other Task 
             return false; 
            }); 
    } 

public bool Bar() 
    { 
     //do a lot of work without awaiting any other task 
     return false; 
    } 

Im Allgemeinen ich schaffen und solche Methoden wie die Foo Beispiel verbrauchen, aber es gibt ein ‚Extra‘ Lambda die gesamte Verfahren Logik enthält, die nicht sieht sehr hübsch imho. Eine andere Option ist die Verwendung einer Methode wie dem Bar-Beispiel, aber ich denke, das ist noch schlimmer, weil es nicht klar ist, dass diese Methode async ausgeführt werden sollte (abgesehen von richtigen Methodennamen wie BarAsync) und die Task.Factory.StartNew muss mehrmals im Programm wiederholt werden. Ich weiß nicht, wie ich dem Compiler nur sagen soll, dass diese Methode eine Aufgabe zurückgibt, bitte verpacken Sie sie als Ganzes in eine Aufgabe, wenn sie aufgerufen wird, was ich tun möchte.

Endlich meine Frage: Was ist der beste Weg, eine solche Methode zu schreiben? Kann ich das "zusätzliche" Lambda loswerden (ohne natürlich eine zusätzliche benannte Methode hinzuzufügen)?

EDIT Wie Servy angegeben immer guter Grund ist eine synchrone Version des Verfahrens zu haben. Eine Async-Version sollte nur dann zur Verfügung gestellt werden, wenn dies absolut notwendig ist (Stephen Cleary's Link).

+0

'' ohne eine zusätzliche benannte Methode natürlich hinzuzufügen ''warum das als eine Option ablehnen? Erstellen Sie 'public bool Bar' und' public Task BarAsync'. – Servy

+0

Ich wollte Overhead vermeiden. Wenn es sinnvoll ist, eine synchrone oder asynchrone Methode zu verwenden, ist das in Ordnung. Wenn nicht, würde es ein öffentliches BarAsync und eine private Bar geben (um es zu verstecken) und in diesem Fall sehe ich nicht viel Grund dafür. – marce

Antwort

3

Würde die Welt enden, wenn jemand Bar aufrufen wollte, ohne es in einem neuen Thread/Task zu starten? Was ist, wenn es eine andere Methode gibt, die bereits in einem Hintergrundthread ist, so dass keine neue Aufgabe gestartet werden muss, um nur diesen lang laufenden Code auszuführen? Was passiert, wenn die Methode in eine Klassenbibliothek umstrukturiert wird, die sowohl aus dem Kontext der Desktop-App als auch aus einem ASP- oder Konsolenkontext aufgerufen wird? In diesen anderen Kontexten müsste diese Methode wahrscheinlich nur direkt ausgeführt werden, nicht als Task.

Ich würde sagen, Ihr Code sollte aussehen wie Bar tut es, es sei denn, es ist absolut zwingend, dass, unter keinen Umständen, sollte dieser Code ausgeführt werden, ohne eine neue Task starten.

Beachten Sie auch, dass mit neueren Versionen von .NET sollten Sie von Task.Factory.StartNew zu Task.Run wechseln, so dass die Menge an Code (ein bisschen) gehen sollte.

+1

Okay, habe deinen Standpunkt verstanden. Also gibt es kein "erzwinge diese Methode in eine Aufgabe" -Funktion, weil es normalerweise eine schlechte Idee ist :) Und danke für den Task.Run-Hinweis, habe ich irgendwie verpasst ... – marce

+3

Siehe auch: [Sollte ich asynchrone Wrapper für synchrone Methoden verfügbar machen? ] (http://blogs.msdn.com/b/pfxteam/archive/2012/03/24/10287244.aspx) –