Воспроизвести записанный поток данных в F # - PullRequest
3 голосов
/ 21 марта 2011

Я записал котировки акций в реальном времени в базе данных SQL с полями Id, Last и TimeStamp. Последним является текущая цена акций (как двойная), а TimeStamp - это DateTime, когда было зафиксировано изменение цены.

Я хотел бы воспроизвести этот поток так же, как он поступил. Это означает, что если изменение цены было первоначально на расстоянии 12 секунд, то срабатывание события изменения цены (или что-то подобное) должно быть на расстоянии 12 секунд.

В C # я мог бы создать коллекцию, отсортировать ее по DateTime, а затем вызвать событие, используя разницу во времени, чтобы узнать, когда сработать при следующем изменении цены. Я понимаю, что в F # есть много интересных новинок, связанных с событиями, но я не знаю, как бы я начал это в F #. Какие-нибудь мысли / фрагменты кода / полезные ссылки о том, как я мог бы продолжить это?

1 Ответ

11 голосов
/ 21 марта 2011

Я думаю, вам понравится решение F # :-).

Для простоты примера я храню цену и временные метки в списке, содержащем кортежи (первый элемент - это задержка с последнего обновления, а второй - цена). Не должно быть слишком сложно превратить ваши входные данные в этот формат. Например:

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

Теперь мы можем создать новое событие, которое будет использоваться для воспроизведения процесса. После его создания мы немедленно подключаем некоторый обработчик, который будет печатать обновления цен:

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

Последний шаг - реализация воспроизведения - это можно сделать с помощью асинхронного рабочего процесса, который циклически перебирает значения, асинхронно ожидает указанное время и затем запускает событие:

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

Я запускаю рабочий процесс, используя StartImmediate, что означает, что он будет работать в текущем потоке (ожидание асинхронно, поэтому он не блокирует поток). Хранение всего однопоточного делает его немного проще (например, вы можете безопасно получить доступ к элементам управления GUI).

РЕДАКТИРОВАТЬ Чтобы обернуть функциональность в некоторый компонент, который может использоваться из других частей приложения, вы можете определить тип, подобный этому:

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

Пользователи могут затем создать экземпляр типа, прикрепить свои обработчики событий, используя stream.PriceChanged.Add(...), а затем начать воспроизведение записанных изменений, используя Reply()

.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...