Ich habe eine einfache synchrone Methode, die so aussieht:
%Vor%Da die Methode Teil einer Webanwendung ist, ist es sinnvoll, alle Ressourcen so effektiv wie möglich zu nutzen. Daher möchte ich die Methode in eine asynchrone ändern. Die einfachste Möglichkeit ist, etwas wie folgt zu tun:
%Vor% Ich bin kein Experte in async
/ await
oder IEnumerable
. Wie ich jedoch verstehe, "verbraucht" die Verwendung dieses Ansatzes die Vorteile von IEnumerable
, weil die Aufgabe erwartet wird, bis die gesamte Sammlung geladen ist, wodurch die "Faulheit" der Sammlung IEnumerable
wegfällt.
In anderen StackOverflow-Posts habe ich mehrere Vorschläge zur Verwendung von Rx.NET (oder System.Reactive) gelesen. Beim schnellen Durchsuchen der Dokumentation habe ich gelesen, dass IObservable<T>
ihre asynchrone Alternative zu IEnumerable<T>
ist. Die naive Methode zu verwenden und zu versuchen, Folgendes einzugeben, funktionierte jedoch nicht:
Ich habe einen Kompilierungsfehler, dass IObservable<T>
weder GetEnumerator()
, noch GetAwaiter()
implementiert - somit kann nicht yield
und async
verwendet werden. Ich habe die Dokumentation von Rx.NET nicht tiefer gelesen, daher benutze ich die Bibliothek wahrscheinlich nur falsch. Aber ich wollte keine Zeit damit verbringen, ein neues Framework zu lernen, um eine einzelne Methode zu modifizieren.
Mit den neuen Möglichkeiten in C # 7 es ist jetzt möglich, benutzerdefinierte Typen zu implementieren. Somit könnte ich theoretisch eine IAsyncEnumerable
implementieren, die sowohl GetEnumerator()
als auch GetAwaiter()
Methoden definieren würde. Aus meiner vorherigen Erfahrung erinnere ich mich jedoch an einen erfolglosen Versuch, eine benutzerdefinierte Implementierung von GetEnumerator()
zu erstellen ... Ich landete mit einer einfachen Liste, versteckt in einem Container.
Somit haben wir 4 mögliche Ansätze, um die Aufgabe zu lösen:
IEnumerable
IEnumerable
in einem Task<T>
IAsyncEnumerable
mit C # 7-Funktionen Was sind die Vor- und Nachteile jedes dieser Versuche? Welche davon hat den größten Einfluss auf die Ressourcennutzung?
- Halten Sie den Code synchron, aber mit IEnumerable
- Ändern Sie es in asynchron, aber wickeln Sie IEnumerable in eine Aufgabe
ein- Lerne und verwende Rx.NET (System.Reactive)
- Erstellen Sie ein benutzerdefiniertes IAsyncEnumerable mit C # 7-Features
Was sind die Vor- und Nachteile jedes dieser Versuche? Welche von ihnen hat den größten Einfluss auf die Ressourcennutzung?
In Ihrer Situation klingt es wie die beste Option ist Task<IEnumerable<T>>
. Hier ist, was jede Option auszeichnet:
Synchroner Code (oder paralleler synchroner Code) zeichnet sich aus, wenn keine E / A, aber eine hohe CPU-Auslastung vorhanden ist. Wenn der E / A-Code synchron abläuft (wie bei der ersten Methodenimplementierung), zündet die CPU nur Zyklen, während sie darauf wartet, dass der Webdienst reagiert und nichts tut.
Task<IEnumerable<T>>
ist für den Fall vorgesehen, dass eine E / A-Operation eine Sammlung abruft. Der Thread, der auf die E / A-Operation wartet, kann dann noch etwas anderes auf ihn warten lassen.
Das klingt nach deinem Fall.
Rx eignet sich am besten für Push-Szenarien: Wo Daten an Ihren Code "gepusht" werden, auf den Sie antworten möchten. Übliche Beispiele sind Anwendungen, die Börsenkursdaten oder Chat-Anwendungen erhalten.
IAsyncEnumerable
ist für eine Sammlung gedacht, bei der jedes Element eine asynchrone Aufgabe erfordert oder generiert. Ein Beispiel: Iterieren über eine Sammlung von Elementen und Ausführen einer Art eindeutiger DB-Abfrage für jede einzelne. Wenn Ihre Transform
tatsächlich eine I / O-gebundene asynchrone Methode ist, dann ist dies wahrscheinlich sinnvoller.
Tags und Links c# asynchronous .net-core system.reactive