Best Practice für die Verwendung von async warten in Webapi

8

Ich habe .NET Core Web API als Service-Schicht. Service-Ebene hat alle EF-Code.

Wenn der Basiscontroller diesen Code hat

%Vor%

In der Controller-Aktion wickle ich alle Anrufe in den oben beschriebenen Dienst, z. :

%Vor%

Ist dies das richtige Muster für morgen, kann es sein, dass ich mehr als einen Serviceaufruf aktiviere oder andere Webdienste anrufe. Bitte beraten.

    
krishna 16.02.2017, 14:03
quelle

2 Antworten

18
  

Ich möchte, dass meine API von asynchronen Wartezeiten profitiert. Das obige Muster dient diesen Bedürfnissen.

Nein, tut es nicht. Das Ausführen synchronen Arbeitens im Thread-Pool führt zu den Nachteilen synchronen und asynchronen Codes mit den Vorteilen beider.

  

Etwas Dienst hat einige Crud-Operationen, die entityframework core verwenden

Momentan ist Ihre Aktionsmethode etwas, was ich "falsches asynchrones" nenne - es sieht asynchron aus (z. B. mit await ), aber tatsächlich wird gerade blockierender Code in einem Hintergrund-Thread ausgeführt. Auf ASP.NET möchten Sie echte Asynchronität, was bedeutet, dass Sie den gesamten Weg async sein müssen. Weitere Informationen dazu, warum das bei ASP.NET schlecht ist, finden Sie in der ersten Hälfte meiner Einführung in async on ASP.NET Artikel (es handelt sich hauptsächlich um ASP.NET Nicht-Kern, aber der erste Teil spricht über synchrone vs asynchrone Anfragen ist gültig für jede Art von Server).

Um dies wirklich asynchron zu machen, sollten Sie auf der untersten Ebene beginnen - in diesem Fall ruft Ihr EFCore auf. Sie alle unterstützen die Asynchronität. Ersetzen Sie also API-Aufrufe wie x.FirstOrDefault() durch await x.FirstOrDefaultAsync() (und dasselbe für alle Ihre Erstellungen / Aktualisierungen / Löschungen usw.).

Dann erlaube async / await natürlich von dort zu wachsen; Der Compiler wird Sie führen. Am Ende erhalten Sie asynchrone Methoden für Ihre somethingService , die als solche konsumiert werden können:

%Vor%     
Stephen Cleary 16.02.2017 14:26
quelle
6

Okay, zu allererst sollten Sie Task.Factory.StartNew nicht mehr verwenden und Task.Run nur verwenden, wenn Sie stark an die CPU gebundene Arbeit haben, die Sie in einem Thread-Pool-Thread ausführen möchten. In Ihrem Fall brauchen Sie das überhaupt nicht. Außerdem sollten Sie daran denken, dass Sie Task.Run nur beim Aufruf einer Methode und nicht bei der Implementierung der Methode verwenden sollten. Sie können mehr darüber hier lesen.

Was Sie in Ihrem Fall wirklich wollen, ist eine asynchrone Arbeit in Ihrem Dienst (ich bin mir nicht sicher, ob Sie in Ihrem Fall sogar einen Dienst benötigen), wenn Sie tatsächlich einen Anruf bei der Datenbank machen und Async verwenden möchten / warten und nicht nur ein paar Sachen auf einem Hintergrund-Thread ausführen.

Grundsätzlich sollte Ihr Service in etwa so aussehen (wenn Sie sicher sind, dass Sie einen Service benötigen):

%Vor%

Wie Sie sehen können, macht Ihr Dienst jetzt asynchrone Aufrufe an die Datenbank und das ist im Grunde das, was Ihr Muster sein sollte. Sie können dies auf alle Ihre Operationen anwenden (hinzufügen / löschen / etc ..)

Nachdem Sie Ihren Dienst asynchron erstellt haben, sollten Sie in der Lage sein, die Daten in der Aktion problemlos zu nutzen.

Ihre Aktionen sollten in etwa so aussehen:

%Vor%     
Kerim Emurla 16.02.2017 14:37
quelle