wake-up-neo.com

Web Api - Feuer und Vergessen

Ich habe eine Web-API-Aktion, bei der ich eine Aufgabe ausführen und diese Aufgabe vergessen muss .. __ So ist meine Methode jetzt organisiert:

public async Task<SomeType> DoSth()
{
    await Task.Run(...);
    .....
    //Do some other work
}

Die Sache ist, dass es offensichtlich an der Wartelinie stoppt, wenn es fertig ist, und erst dann die Arbeit fortsetzt. Und ich muss "feuern und vergessen" Soll ich Task.Run () ohne async-waitit aufrufen?

21
D. Jones

Echte Feuer- und Vergessungsaufgaben können in asp.net schwierig sein, da sie oft zusammen mit der Anforderung sterben, die sie als Teil von erstellt haben. 

Wenn Sie 4.5.2 oder höher verwenden, können Sie QueueBackgroundWorkItem verwenden, um die Task auszuführen. Durch das Registrieren von Aufgaben über diese Methode verzögert die AppDomain try, um das Herunterfahren zu verzögern, bis alle abgeschlossen sind. Es kann jedoch vorkommen, dass sie abgebrochen werden, bevor sie abgeschlossen sind. Dies ist wahrscheinlich das Einfachste, aber es ist einen Blick wert, um genau zu sehen, welche Instanzen dazu führen können, dass Jobs abgebrochen werden.

HostingEnvironment.QueueBackgroundWorkItem(async cancellationToken =>
{
  await Task.Run(...);
});

Es gibt ein Tool namens hangfire , das einen permanenten Speicher verwendet, um sicherzustellen, dass eine Aufgabe abgeschlossen ist und über eine integrierte Wiederholungs- und Fehleraufzeichnungsfunktion verfügt. Dies ist mehr für "Hintergrundaufgaben", passt aber zu Feuer und Vergessen. Dies ist relativ einfach einzurichten und bietet eine Vielzahl von Backing-Stores. Ich kann mich nicht an die genauen Details erinnern, aber einige benötigen eine Lizenz, andere nicht (wie MSSQL).

5
Fermin

Verwenden Sie diese Option für Feuer und Vergessen

Task.Factory.StartNew(async () =>
{
    using (HttpClient client = new HttpClient())
    {
        await client.PostAsync("http://localhost/api/action", new StringContent(""));
    }
});
4
Catalin

Ich benutze HangFire .

Das ist das Beste für mich.

Eine einfache Methode für die Hintergrundverarbeitung in .NET- und .NET Core-Anwendungen. Kein Windows-Dienst oder separater Prozess erforderlich.

Durch permanenten Speicher gesichert. Offen und frei für die kommerzielle Nutzung. 

3
Majid gharaei

Niemals feuern und vergessen, denn dann werden keine Fehler angezeigt, was zu einer sehr umständlichen Fehlerbehebung führt, wenn ein Fehler auftritt (die Task-Methode kann keine eigene Ausnahmebehandlung ausführen, da dies möglicherweise nicht der Fall ist erfolgreich starten). Es sei denn, Sie haben wirklich nichts dagegen, ob die Aufgabe etwas tut oder nicht, aber das ist ziemlich ungewöhnlich (da, wenn es Ihnen wirklich egal ist, warum laufen Sie die aufgabe an erster stelle)? Erstellen Sie Ihre Aufgabe mindestens mit einem Fortsetzung :

Task.Run(...)
  .ContinueWith(t => 
    logException(t.Exception.GetBaseException()),
    TaskContinuationOptions.OnlyOnFaulted
  )
;

Sie können dies nach Bedarf verfeinern.

Im speziellen Fall einer Web-API möchten Sie möglicherweise warten, bis Ihre Hintergrundaufgaben abgeschlossen sind, bevor Sie Ihre Anforderung abschließen. Wenn Sie dies nicht tun, lassen Sie Dinge im Hintergrund laufen, die möglicherweise falsch darstellen, wie viel Last Ihr Service wirklich aufnehmen kann, oder stellen Sie sogar die Arbeit ein, wenn Clients zu viele Anfragen abfeuern und Sie nichts unternehmen, um sie zu drosseln. Sie können Aufgaben sammeln und am Ende eine await Task.WhenAll(...) ausgeben, um dies zu erreichen. Auf diese Weise können Sie weiterhin nützliche Arbeit leisten, während Ihre Hintergrundaufgaben vergehen. Sie kehren jedoch erst zurück, wenn alles erledigt ist.

2
Jeroen Mostert

Ich stimme mit anderen überein, dass Sie Ihren Anruf nicht einfach vergessen sollten. Um Ihre Frage zu beantworten, wird der Anruf jedoch nicht blockiert, wenn Sie waitit aus der Task.Run () -Zeile entfernen (siehe hier ).

public async Task<SomeType> DoSth()
{
    Task.Run(...);
    .....
    //Do some other work while Task.Run() continues in parallel.
}
0
Avinash Kumar

Es gibt hier ein paar Beiträge, die das "Nie Feuer und Vergessen", dessen Fehler usw. schieben.

Die Wahrheit ist, dass es aus bestimmten Gesichtspunkten nicht falsch ist. In gewisser Weise falsch beschrieben.

Was dies wirklich bedeuten sollte, ist "der Benutzer sollte in der Lage sein, zu feuern und zu vergessen, aber es sollte dem Entwickler/Besitzer trotzdem Bescheid geben."

Ein gutes Beispiel ist ein Kontaktformular auf einer Website. Der Kunde füllt das Formular aus und sendet hinter den Kulissen eine E-Mail an den Eigentümer der Site. Einige E-Mail-Server brauchen viel zu lange, um die Sendung zu verarbeiten. Pakete wie Hangfire (die ich verwenden würde) senden sie an einen anderen Prozess außerhalb des Webservers "Thread".

Ja, dies sollte den Entwickler/Eigentümer irgendwie informieren (und die Kontaktdetails beibehalten), wenn ein Fehler auftritt. Dies sollte jedoch den potenziellen Kontakt in keiner Weise über das Problem informieren. (es sei denn, Sie möchten einen potenziellen Kunden verlieren)

0

Für das Aufrufen einer WebApi-Methode mit Feuer und Vergessen habe ich den folgenden Code verwendet, um sicherzustellen, dass eine OK-Antwort zurückgegeben wird. In meinem Fall wird das beim Login erstellte Inhaberauthentifizierungs-Token in einem Cookie gespeichert:

...
FireAndForget().Wait();
...

private async Task FireAndForget()
    {
        using (var httpClient = new HttpClient())
        {
            HttpCookie cookie = this.Request.Cookies["AuthCookieName"];
            var authToken = cookie["AuthTokenPropertyName"] as string;
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
            using (var response = await httpClient.GetAsync("http://localhost/api/FireAndForgetApiMethodName"))
            {
                //will throw an exception if not successful
                response.EnsureSuccessStatusCode();
            }
        }
    }
0
CAK2