1

Ich habe den Quellcode UserManager.cs gelesen und ich habe in den folgenden Block trat:Microsoft.AspNetCore.Identity Usermanager GetUserAsync

 public virtual Task<TUser> GetUserAsync(ClaimsPrincipal principal) 
    { 
     if (principal == null) 
     { 
      throw new ArgumentNullException(nameof(principal)); 
     } 
     var id = GetUserId(principal); 
     return id == null ? Task.FromResult<TUser>(null) : FindByIdAsync(id); 
    } 

Ich habe sehr neugierig gewesen, wenn es einen Grund gibt, warum das obige nicht so ist:

 public virtual async Task<TUser> GetUserAsync(ClaimsPrincipal principal) 
    { 
     if (principal == null) 
     { 
      throw new ArgumentNullException(nameof(principal)); 
     } 
     var id = GetUserId(principal); 
     return id == null ? await Task.FromResult<TUser>(null) : await FindByIdAsync(id); 
    } 

Wie Sie sehen können habe ich nur async/await hinzugefügt.

* Ich implementiere die UserManager-Klasse mit einem anderen ORM.

Antwort

4

Da ich es nicht geschrieben habe kann ich nicht sicher wissen. ;) Aber ich denke, es ist in Bezug auf die return await-anti-Muster.

Es gibt sogar ein Problem auf GitHub, wo die Anfrage ist, dass Roslyn es beim Kompilieren behandelt.

Optimize an async method that ends "return await e" to be non-async "return e"

diese Optimierung würde die Leistung einer Asynchron-Methode erwarten, deren Verbesserung erst am Ende erscheint. Nicht bei der Erstellung von Debug-Code und nicht bei Verschachtelung in einem try-Block.

den ausgezeichneten Kommentar von damien_the_unbeliever zu zitieren, die er auf this question geschrieben

await ist eine Möglichkeit, die aktuelle Methode der Pause, bis ein anderes Stück Code seine Arbeit geleistet hat. Wenn alles, was Ihre Methode tun wird, wenn es wieder aufgenommen wird, ist zu sagen, "Ich bin fertig", dann warum gehen Sie zu allen Aufwand? Davon abgesehen, ist das tatsächliche anti-Muster ist return await wenn dass die nurawait bei dem Verfahren ist (wie hier), und es ist nicht innerhalb eines try Blockes mit einem finally oder einem using Block (in diesem Fall bestehen Zusatzcode nach der Rückkehr

laufen Bei der Verwendung von await/async sollte man es schafft der Ober bewusst sein

diese beiden Klassen Nehmen sie zum Beispiel:.

public class BaseClass 
{ 
    public async Task<int> GetIdAsync() 
    { 
     return await Task.Run(() => 100); 
    } 
} 

public class Foo : BaseClass 
{ 
    public Task<int> GetId() 
    { 
     return GetIdAsync(); 
    } 
} 


public class Bar : BaseClass 
{ 
    public async Task<int> GetId() 
    { 
     return await GetIdAsync(); 
    } 
} 

Wenn Sie den Code aus Bar mit ILSpy decompile etwas wie folgt aussehen:

public class Bar : BaseClass 
{ 
    [DebuggerStepThrough, AsyncStateMachine(typeof(Bar.<GetId>d__0))] 
    public Task<int> GetId() 
    { 
     Bar.<GetId>d__0 <GetId>d__ = new Bar.<GetId>d__0(); 
     <GetId>d__.<>4__this = this; 
     <GetId>d__.<>t__builder = AsyncTaskMethodBuilder<int>.Create(); 
     <GetId>d__.<>1__state = -1; 
     AsyncTaskMethodBuilder<int> <>t__builder = <GetId>d__.<>t__builder; 
     <>t__builder.Start<Bar.<GetId>d__0>(ref <GetId>d__); 
     return <GetId>d__.<>t__builder.Task; 
    } 
} 

Während Foo wie folgt aussieht:

public class Foo : BaseClass 
{ 
    public Task<int> GetId() 
    { 
     return base.GetIdAsync(); 
    } 
} 

Also, um es zusammenzufassen, wenn Sie einfach, um den Wert von einem Task zurückzugeben, gibt es wirklich keinen Grund zu await es. Stattdessen sollten Sie den Task zurückgeben und den Anruferawait stattdessen Task zurückgeben lassen.Das Erweitern der Task erweitert den Stapel und erstellt einen Overhead, der die Leistung nur negativ beeinflusst.

+0

Und was ist mit Ausnahmeausbreitung. Async/await stellt die Fortsetzung sicher und ermöglicht, dass die Ausnahme korrekt zurückgegeben wird. Wäre es ein Problem, wenn ich nur Aufgabe und eine Ausnahme geworfen wird? Ich habe versucht, eine schnelle Antwort zu finden, wenn async/await den ersten Thread überspringen und mit einem anderen fortfahren kann, aber ich habe das noch nicht geklärt. – BeStelios

+0

Der GitHub-Link behandelt die Behandlung von Ausnahmen. Das Zurückgeben der Aufgabe würde tatsächlich den Stapel für die Ausnahme ändern. Die "Task" muss noch abgewartet werden, daher sollte die Ausnahme immer noch zurückgegeben werden, aber wahrscheinlich in einem anderen Stack. – smoksnes