Bridging mit vorhandenen asynchronen Quellen
Neben .NET-Ereignissen sind im .NET Framework weitere asynchrone Datenquellen vorhanden. Eines davon ist das asynchrone Methodenmuster. In diesem Entwurfsmuster werden zwei Methoden bereitgestellt. Eine Methode (normalerweise als BeginX bezeichnet) wird verwendet, um die Berechnung zu starten und gibt ein IAsyncResult-Handle zurück, das an die zweite Methode (normalerweise als EndX bezeichnet) übergeben wird, die dann das Ergebnis der Berechnung abruft. Die Vervollständigung wird in der Regel durch Implementieren eines AsyncCallback-Delegaten oder Abrufen von IAsyncResult.IsCompleted signalisiert. Code, der diesem Muster entspricht, ist oft schwer zu lesen und zu verwalten. In diesem Thema wird gezeigt, wie Sie Rx-Factorymethoden verwenden, um solche asynchronen Datenquellen in beobachtbare Sequenzen zu konvertieren.
Konvertieren von asynchronen Mustern in beobachtbare Sequenzen
Viele asynchrone Methoden in .NET werden mit Signaturen wie BeginX und EndX geschrieben, wobei X der Methodenname ist, der asynchron ausgeführt wird. BeginX verwendet Argumente, um die -Methode auszuführen, ein AsyncCallback, bei dem es sich um eine Aktion handelt, die ein IAsyncResult-Objekt annimmt und nichts zurückgibt, und schließlich einen Objektzustand. EndX verwendet das IAsyncResult, das von AsyncCallback übergeben wird, um den Wert des asynchronen Aufrufs abzurufen.
Der FromAsyncPattern-Operator des Observable-Typs umschließt die Begin- und End-Methoden (die als Parameter an den Operator übergeben werden) und gibt eine Funktion zurück, die die gleichen Parameter wie Begin akzeptiert und eine beobachtbare zurückgibt. Dieses beobachtbare Objekt stellt eine Sequenz dar, die einen einzelnen Wert veröffentlicht, der das asynchrone Ergebnis des soeben angegebenen Aufrufs ist.
Im folgenden Beispiel konvertieren wir BeginRead und EndRead für ein Stream-Objekt , das das IAsyncResult-Muster verwendet, in eine Funktion, die eine beobachtbare Sequenz zurückgibt. Für die generischen Parameter des FromAsyncPattern-Operators geben wir die Typen der Argumente von BeginRead bis zum Rückruf an. Da die EndRead-Methode einen Wert zurückgibt, fügen wir diesen Typ als endgültigen generischen Parameter für FromAsyncPattern an. Wenn Sie var
auf für read
zeigen, werden Sie feststellen, dass der Rückgabewert von FromAsyncPattern ein Funktionsdelegat ist, der über die folgende Signatur verfügt: Func<byte[], int32,int32, IObservable<int32>>
. Dies bedeutet, dass diese Funktion drei Parameter (die gleichen für BeginRead) akzeptiert und ein IObservable<Int32> zurückgibt. Dieser IObservable-Wert enthält einen Wert, die ganze Zahl, die von EndRead zurückgegeben wird, und enthält die Anzahl der aus dem Stream gelesenen Bytes zwischen null (0) und der Anzahl der angeforderten Bytes. Da wir jetzt ein IObservable anstelle eines IAsyncResult erhalten, können wir alle LINQ-Operatoren verwenden, die für Observables verfügbar sind, und sie abonnieren, analysieren oder verfassen.
Stream inputStream = Console.OpenStandardInput();
var read = Observable.FromAsyncPattern<byte[], int, int, int>(inputStream.BeginRead, inputStream.EndRead);
byte[] someBytes = new byte[10];
IObservable<int> source = read(someBytes, 0, 10);
IDisposable subscription = source.Subscribe(
x => Console.WriteLine("OnNext: {0}", x),
ex => Console.WriteLine("OnError: {0}", ex.Message),
() => Console.WriteLine("OnCompleted"));
Console.ReadKey();