programmierung So rufen Sie eine asynchrone Methode in C#ohne Wartezeit sicher auf




c# task beispiel (4)

Sie sollten zuerst in Betracht ziehen, GetStringData einer async Methode zu machen und sie await die von MyAsyncMethod Aufgabe MyAsyncMethod .

Wenn Sie absolut sicher sind, dass Sie keine Ausnahmen von MyAsyncMethod oder wissen, wann sie abgeschlossen sind, können Sie MyAsyncMethod tun:

public string GetStringData()
{
  var _ = MyAsyncMethod();
  return "hello world";
}

Übrigens, das ist kein "häufiges Problem". Es ist sehr selten, etwas Code ausführen zu wollen und es nicht zu interessieren, ob es vollständig ist und es nicht wichtig ist, ob es erfolgreich abgeschlossen wird.

Aktualisieren:

Da Sie auf ASP.NET sind und gerne früher zurückkehren möchten, ist möglicherweise mein Blogbeitrag zu diesem Thema nützlich . Allerdings wurde ASP.NET nicht dafür entwickelt, und es gibt keine Garantie, dass der Code nach der Antwort ausgeführt wird. ASP.NET wird sein Bestes tun, um es laufen zu lassen, aber es kann nicht garantieren.

Also, dies ist eine gute Lösung für etwas Einfaches wie das Werfen eines Ereignisses in ein Protokoll, wo es nicht wirklich wichtig ist, wenn Sie ein paar hier und da verlieren. Es ist keine gute Lösung für geschäftskritische Vorgänge. In diesen Situationen müssen Sie eine komplexere Architektur mit einer beständigen Methode zum Speichern der Vorgänge (z. B. Azure Queues, MSMQ) und eines separaten Hintergrundprozesses (z. B. Azure Worker Role, Win32-Dienst) verwenden, um sie zu verarbeiten.

Ich habe eine async Methode, die keine Daten zurückgibt:

public async Task MyAsyncMethod()
{
    // do some stuff async, don't return any data
}

Ich rufe dies von einer anderen Methode, die einige Daten zurückgibt:

public string GetStringData()
{
    MyAsyncMethod(); // this generates a warning and swallows exceptions
    return "hello world";
}

MyAsyncMethod() Sie MyAsyncMethod() ohne darauf zu warten, wird im Visual Studio eine Warnung MyAsyncMethod() "dass dieser Aufruf nicht abgewartet wird und die aktuelle Methode weiterhin ausgeführt wird, bevor der Anruf beendet wird ". Auf der Seite für diese Warnung heißt es:

Sie sollten die Warnung nur unterdrücken, wenn Sie sicher sind, dass Sie nicht auf den Abschluss des asynchronen Aufrufs warten möchten und dass die aufgerufene Methode keine Ausnahmen auslöst .

Ich bin sicher, ich möchte nicht warten, bis der Anruf abgeschlossen ist. Ich brauche oder habe keine Zeit dazu. Aber der Aufruf könnte Ausnahmen auslösen.

Ich bin ein paar Mal auf dieses Problem gestoßen und ich bin mir sicher, dass es ein häufiges Problem ist, das eine gemeinsame Lösung haben muss.

Wie kann ich eine asynchrone Methode sicher aufrufen, ohne auf das Ergebnis zu warten?

Aktualisieren:

Für Leute, die vorschlagen, dass ich nur auf das Ergebnis warte, handelt es sich um Code, der auf eine Webanforderung in unserem Webdienst (ASP.NET Web API) reagiert. Das Warten auf einen UI-Kontext hält den UI-Thread frei, wartet jedoch in einem Webanforderungsaufruf darauf, dass der Task beendet wird, bevor er auf die Anforderung reagiert, wodurch die Antwortzeiten ohne Grund ansteigen.


Ich denke, die Frage stellt sich, warum sollten Sie das tun? Der Grund für async in C # 5.0 ist, dass Sie ein Ergebnis erwarten können. Diese Methode ist eigentlich nicht asynchron, sondern wird einfach zu einem Zeitpunkt aufgerufen, um den aktuellen Thread nicht zu sehr zu stören.

Vielleicht ist es besser, einen Thread zu starten und ihn alleine zu beenden.


Die Antwort von Peter Ritchie war, was ich wollte, und Stephen Cleary's Artikel über die frühe Rückkehr in ASP.NET war sehr hilfreich.

Als ein allgemeineres Problem (nicht spezifisch für einen ASP.NET-Kontext) demonstriert die folgende Konsolenanwendung die Verwendung und das Verhalten von Peters Antwort mit Task.ContinueWith(...)

static void Main(string[] args)
{
  try
  {
    // output "hello world" as method returns early
    Console.WriteLine(GetStringData());
  }
  catch
  {
    // Exception is NOT caught here
  }
  Console.ReadLine();
}

public static string GetStringData()
{
  MyAsyncMethod().ContinueWith(OnMyAsyncMethodFailed, TaskContinuationOptions.OnlyOnFaulted);
  return "hello world";
}

public static async Task MyAsyncMethod()
{
  await Task.Run(() => { throw new Exception("thrown on background thread"); });
}

public static void OnMyAsyncMethodFailed(Task task)
{
  Exception ex = task.Exception;
  // Deal with exceptions here however you want
}

GetStringData() gibt früh zurück, ohne MyAsyncMethod() zu warten, und Exceptions, die in MyAsyncMethod() werden, werden in OnMyAsyncMethodFailed(Task task) und nicht in try / catch around GetStringData()


Ich habe diese Lösung:

public async Task MyAsyncMethod()
{
    // do some stuff async, don't return any data
}

public string GetStringData()
{
    // Run async, no warning, exception are catched
    RunAsync(MyAsyncMethod()); 
    return "hello world";
}

private void RunAsync(Task task)
{
    task.ContinueWith(t =>
    {
        ILog log = ServiceLocator.Current.GetInstance<ILog>();
        log.Error("Unexpected Error", t.Exception);

    }, TaskContinuationOptions.OnlyOnFaulted);
}




async-await