web-dev-qa-db-de.com

Rufe die asynchrone Methode auf, ohne auf # 2 zu warten

Ich habe eine asynchrone Methode:

public async Task<bool> ValidateRequestAsync(string userName, string password)
{
    using (HttpClient client = new HttpClient())
    {
        HttpResponseMessage response = await client.GetAsync(url);
        string stringResponse = await response.Content.ReadAsStringAsync();

        return bool.Parse(stringResponse);
    }
}

Ich nenne diese Methode so:

bool isValid = await ValidateRequestAsync("user1", "pass1");

Kann ich dieselbe Methode von einer synchronen Methode aus aufrufen, ohne das Schlüsselwort await zu verwenden?

Ex:

public bool ValidateRequest(string userName, string password)
{
    return ValidateRequestAsync(userName, password).Result;
}

Ich denke, das wird eine Sackgasse verursachen.

EDIT

Wenn Sie die oben beschriebene Methode aufrufen, wird der Aufruf niemals beendet. (Die Methode erreicht nicht mehr das Ende)

40
Catalin

Wenn Sie eine asynchrone Methode aus einem einzelnen Thread-Ausführungskontext aufrufen, z. B. einem UI-Thread, und synchron auf das Ergebnis warten, besteht eine hohe Wahrscheinlichkeit für einen Deadlock. In Ihrem Beispiel ist diese Wahrscheinlichkeit 100%

Denk darüber nach. Was passiert, wenn Sie anrufen?

ValidateRequestAsync(userName, password).Result

Sie rufen die Methode ValidateRequestAsync auf. Dort rufen Sie ReadAsStringAsync auf. Das Ergebnis ist, dass eine Aufgabe an den Benutzeroberflächenthread zurückgegeben wird und eine Fortsetzung geplant ist, die auf dem Benutzeroberflächenthread ausgeführt wird, sobald sie verfügbar ist. Aber es wird natürlich niemals verfügbar sein, da es darauf wartet (blockiert), dass die Aufgabe beendet wird. Die Aufgabe kann jedoch nicht abgeschlossen werden, da sie darauf wartet, dass der UI-Thread verfügbar wird. Sackgasse.

Es gibt Möglichkeiten, diesen Stillstand zu verhindern, aber alle sind eine schlechte Idee. Der Vollständigkeit halber könnte Folgendes funktionieren:

Task.Run(async () => await ValidateRequestAsync(userName, password)).Result;

Dies ist eine schlechte Idee, da Sie immer noch das Warten auf Ihren UI-Thread blockieren und nichts Nützliches tun.

Was ist also die Lösung? Gehen Sie den ganzen Weg asynchron. Der ursprüngliche Aufrufer im UI-Thread ist wahrscheinlich eine Ereignisbehandlungsroutine. Stellen Sie also sicher, dass diese asynchron ist.

63

sie können auch return ValidateRequestAsync (Benutzername, Passwort) .GetAwaiter (). GetResult () verwenden.

5
savagepanda