问题描述
我在SQL数据库中记录了实时股票报价,其中字段 Id
,最后
c $ c> TimeStamp 。最后是当前股价(作为双倍), TimeStamp
是记录价格变化时的 DateTime
。
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.
我想以相同的方式重播此流,意味着如果价格变化最初为12秒,那么价格变化事件触发)应该相隔12秒。
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.
在C#中,我可以创建一个集合,通过 DateTime
排序,然后使用时间差知道什么时候开火下一个价格变化。我意识到F#有很多很酷的新事物与事件有关,但我不知道我怎么会在F#开始这个。
In C# I might create a collection, sort it 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?
推荐答案
我认为你会喜欢F#的解决方案:-)。
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
我使用 StartImmediate启动工作流程
这意味着它将在当前线程上运行(等待是异步的,因此它不会阻塞线程)。保持单线程的一切使它变得更简单(例如,您可以安全地访问GUI控件)。
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 可以从应用程序的其他部分使用,您可以定义类型如下:
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
然后用户可以创建类型的实例,使用<$ c $附加他们的事件处理程序c> stream.PriceChanged.Add(...),然后使用 Reply()
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()
这篇关于重播F#中记录的数据流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!