开发者

Replay Recorded Data Stream in F#

开发者 https://www.devze.com 2023-02-17 20:33 出处:网络
I have recorded real-time stock quotes in an SQL database with fields Id, Last, and TimeStamp.Last being the current stock price (as a double), and TimeStamp is the DateTime when the price change was

I have recorded real-time stock quotes in an SQL database with fields Id, Last, and TimeStamp. Last being the current stock price (as a double), and TimeStamp is the DateTime when the price change was recorded.

I would like to replay this stream in the same way it came in, meaning if a price change was originally 12 seconds apart then the price change event firing (or something similar) should be 12 seconds apart.

In C# I might create a collection, sort i开发者_开发百科t by the DateTime then fire an event using the difference in time to know when to fire off the next price change. I realize F# has a whole lot of cool new stuff relating to events, but I don't know how I would even begin this in F#. Any thoughts/code snippets/helpful links on how I might proceed with this?


I think you'll love the F# solution :-).

To keep the example simple, I'm storing the price and timestamps in a list containing tuples (the first element is the delay from the last update an the second element is the price). It shouldn't be too difficult to turn your input data into this format. For example:

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

Now we can create a new event that will be used to replay the process. After creating it, we immediatelly attach some handler that will print the price updates:

let evt = new Event<float>()
evt.Publish.Add(printfn "Price updated: %f")

The last step is to implement the replay - this can be done using asynchronous workflow that loops over the values, asynchronously waits for the specified time and then triggers the event:

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

I'm starting the workflow using StartImmediate which means that it will run on the current thread (the waiting is asynchronous, so it doesn't block the thread). Keeping everything single-threaded makes it a bit simpler (e.g. you can safely access GUI controls).

EDIT To wrap the functionality in some component that could be used from other parts of the application, you could define a type like this:

type ReplyDataStream(prices) =
  let evt = new Event<float>()
  member x.Reply() = 
    // Start the asynchronous workflow here
  member x.PriceChanged = 
    evt.Publish

The users can then create an instance of the type, attach their event handlers using stream.PriceChanged.Add(...) and then start the replaying the recorded changes using Reply()

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号