Start async-Methode als Thread oder als Aufgabe
Ich bin neu C#
s await/async
und derzeit spielen Sie ein bisschen herum.
In meinem Szenario habe ich eine einfache client-Objekt, das hat eine WebRequest
Eigenschaft. Der Kunde sollte senden Sie in regelmäßigen Abständen alive-Nachrichten über die WebRequest
s RequestStream
.
Dies ist der Konstruktor des client-Objekts:
public Client()
{
_webRequest = WebRequest.Create("some url");
_webRequest.Method = "POST";
IsRunning = true;
//--> how to start the 'async' method (see below)
}
und die async-lebendig-sender-Methode
private async void SendAliveMessageAsync()
{
const string keepAliveMessage = "{\"message\": {\"type\": \"keepalive\"}}";
var seconds = 0;
while (IsRunning)
{
if (seconds % 10 == 0)
{
await new StreamWriter(_webRequest.GetRequestStream()).WriteLineAsync(keepAliveMessage);
}
await Task.Delay(1000);
seconds++;
}
}
Wie sollte die Methode gestartet werden?
neuen Thread(SendAliveMessageAsync).Start();
oder
Aufgabe.Run(SendAliveMessageAsync); //änderung der Rückgabe-Typ zu Aufgabe
oder
erwarten SendAliveMessageAsync(); //schlägt fehl, da der Konstruktor ist nicht async
Meine Frage ist, mehr über mein persönliches Verständnis von await/async
ich glaube, das ist vielleicht falsch in einigen Punkten.
Die Dritte Möglichkeit ist, werfen
The 'await' operator can only be used in a method or lambda marked with the 'async' modifier
Es ist in der Tat ein Feuer-und-vergessen werden, da es einfach starten sollte ein
Thread
senden alive-Meldungen.Dann
await
ist sinnlos, da man nicht wirklich daran interessiert, zu warten, für Sie zu vervollständigen. Ich würde einfach den thread Ansatz dann. Persönlich halte ich Aufgaben wie kleinere enthaltenen Einheiten von Arbeit, die ausgeführt werden muss asynchron.Sie sollten nie nennen
new StreamWriter(_webRequest.GetRequestStream()).WriteLineAsync(keepAliveMessage)
- erwarten-oder anders - als StreamWriter
ist IDisposable
und müssen ordnungsgemäß entsorgt werden, sobald verwendet. Diese syntax ermöglicht es Ihnen nicht zu nennen .Dipose()
.Gut und gültig-Punkt. Aber dies ist nicht der funktionierende code. Die
StreamWriter
ist auch die Initialisierung im Konstruktor, sondern wird der Einfachheit halber hier nicht gezeigt.
InformationsquelleAutor KingKerosin | 2016-01-15
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich Stimme für "keine der genannten". 🙂
"Feuer-und-vergessen" ist eine schwierige Szenario zu behandeln, richtig. Insbesondere die Fehlerbehandlung ist immer problematisch. In diesem Fall
async void
mag Sie überraschen.Ich lieber explizit speichern die Aufgaben, wenn ich mich nicht
await
ing Sie sofort:Diese mindestens die Konsumenten von
Client
zu erkennen und wiederherstellen von Ausnahmen von derSendAliveMessageAsync
Methode.On a side note, das Muster ist fast gleichwertig zu meinem "asynchrone Initialisierung-Muster.
InformationsquelleAutor Stephen Cleary
Bearbeitet wie die Vorherige Antwort war falsch:
Als es im Konstruktor, ich glaube, Sie hätte sich zu drehen, ein neues thread dafür. Ich persönlich würde das tun, mit
await
funktioniert nicht in Konstruktoren.Hoppla, du hast Recht.
Gibt es einen Unterschied zwischen
Task.Run
undTask.Factory.StartNew
? Oder ist das nur deine persönliche Meinung?Um ehrlich zu sein, ich benutze Aufgabe.Factory.StartNew aus macht der Gewohnheit; Aufgabe.Laufen ist so ziemlich eine Verknüpfung für Sie, so dass, wenn Sie lieber verwenden, gehen Sie nach rechts weiter.
InformationsquelleAutor John Clifford
Da es ein Feuer-und-vergessen Betrieb nehmen, sollten Sie starten Sie es durch
Beachten Sie, dass
await
startet keine neueTask
. Es ist nur syntaktischer Zucker, um zu warten, bis einTask
abgeschlossen.Ein neuer thread wird gestartet mit
Task.Run
.Also innerhalb
SendAliveMessageAsync
sollten Sie beginnen, eine neue Aufgabe:await
funktioniert nicht in Konstruktoren.Aber ruft es mit
SendAliveMessageAsync();
nicht synchron und deshalb der Konstruktor wird nie wieder (weil die Methodenwhile
)?oh wow, wie konnte ich das übersehen. Danke für die Erinnerung
Ja, das loop in einem Konstruktor ist schlecht. Konstruktoren sollten so schnell wie möglich und sollte nie Risiko-eine Ausnahme ausgelöst wird.
siehe mein edit
InformationsquelleAutor Domysee
Hier ist eine option, da kann man das auch nicht nennen
await
aus in einem Konstruktor.Ich würde vorschlagen, mit Microsoft Reaktive Framework (NuGet "Rx-Main").
Würde der code wie folgt Aussehen:
Dieser code übernimmt alle threading erforderlich und ordnungsgemäß entsorgt
StreamWriter
wie es geht.Wann immer Sie wollen, zu stoppen die keep alives einfach anrufen
_subscription.Dispose()
.InformationsquelleAutor Enigmativity
In deinem code gibt es keine Notwendigkeit, mit async/await, richten Sie einfach einen neuen thread auf, führen lange den Betrieb.
Mit
Task.Factory.StartNew(SendAliveMessage, TaskCreationOptions.LongRunning)
um den Vorgang auszuführen.Wenn Sie wirklich wollen, um mit async/await-Muster, nennen es einfach im Konstruktor erwarten, ohne Modifizierer und vergessen Sie es.
Ich denke, es ist keine gute Idee einen lange Laufenden thread oder mithilfe der async/await-Muster. Timer vielleicht besser geeignet in dieser situation.
InformationsquelleAutor cFish