3 Stimmen

Wiedergabe des aufgezeichneten Datenstroms in F#

Ich habe Echtzeit-Aktienkurse in einer SQL-Datenbank mit den Feldern Id, Last und TimeStamp aufgezeichnet. Last ist der aktuelle Aktienkurs (als double) und TimeStamp ist das DateTime, wann die Preisänderung aufgezeichnet wurde.

Ich würde gerne diesen Datenstrom auf die gleiche Weise wiedergeben, wie er hereingekommen ist. Das bedeutet, wenn eine Preisänderung ursprünglich 12 Sekunden auseinander war, sollten Ereignisse von Preisänderungen (oder Ähnliches) auch 12 Sekunden auseinander sein.

In C# könnte ich eine Sammlung erstellen, sie nach DateTime sortieren und dann ein Ereignis auslösen, indem ich die Zeitdifferenz verwende, um zu wissen, wann die nächste Preisänderung erfolgen soll. Mir ist bewusst, dass F# eine Menge cooler neuer Funktionen im Zusammenhang mit Ereignissen hat, aber ich weiß nicht, wie ich damit in F# beginnen sollte. Irgendwelche Gedanken/Codeschnipsel/hilfreiche Links dazu, wie ich damit fortfahren könnte?

11voto

Tomas Petricek Punkte 233658

Ich denke, du wirst die F#-Lösung lieben :-).

Um das Beispiel einfach zu halten, speichere ich den Preis und die Zeitstempel in einer Liste, die Tupel enthält (das erste Element ist die Verzögerung seit dem letzten Update und das zweite Element ist der Preis). Es sollte nicht allzu schwierig sein, deine Eingabedaten in dieses Format umzuwandeln. Zum Beispiel:

let prices = [ (0, 10.0); (1000, 10.5); (500, 9.5); (2500, 8.5) ]

Jetzt können wir ein neues Ereignis erstellen, das zum Wiederholen des Prozesses verwendet wird. Nachdem wir es erstellt haben, hängen wir sofort einen Handler an, der die Preisaktualisierungen ausgibt:

let evt = new Event()
evt.Publish.Add(printfn "Preis aktualisiert: %f")

Der letzte Schritt besteht darin, die Wiedergabe zu implementieren - dies kann mit einem asynchronen Workflow erfolgen, der über die Werte iteriert, asynchron auf die angegebene Zeit wartet und dann das Ereignis auslöst:

async { for delay, price in prices do
          do! Async.Sleep(delay)
          evt.Trigger(price) }
|> Async.StartImmediate

Ich starte den Workflow mit StartImmediate, was bedeutet, dass er auf dem aktuellen Thread ausgeführt wird (das Warten ist asynchron, so dass der Thread nicht blockiert wird). Wenn alles auf einem einzigen Thread bleibt, wird es etwas einfacher (z. B. können GUI-Steuerungen sicher zugänglich sein).

BEARBEITEN Um die Funktionalität in einer Komponente zu kapseln, die von anderen Teilen der Anwendung verwendet werden kann, könntest du einen Typ wie diesen definieren:

type ReplyDataStream(prices) =
  let evt = new Event()
  member x.Reply() = 
    // Starte hier den asynchronen Workflow
  member x.PriceChanged = 
    evt.Publish

Die Benutzer können dann eine Instanz dieses Typs erstellen, ihre Ereignishandler mit stream.PriceChanged.Add(...) anfügen und dann die aufgezeichneten Änderungen mit Reply() wiedergeben.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X