从Observable到可枚举/值而不会阻塞

时间:2012-12-02 06:31:17

标签: f# system.reactive

我遇到了一些阻塞问题。我试图从推动到拉动。即我想在这里访问我的数据,在这种情况下,它是通过我的Observable处理后的数组。

type HistoryBar = 
    {Open: decimal; High: decimal; Low: decimal; Close: decimal; Time: DateTime; Volume: int; RequestId: int; Index: int; Total: int}

let transformBar =
    client.HistoricalData
    |> Observable.map(fun args ->
        {
            Open = args.Open
            High = args.High
            Low =  args.Low
            Close = args.Close
            Time = args.Date
            Volume = args.Volume
            RequestId = args.RequestId
            Index = args.RecordNumber
            Total = args.RecordTotal
       }
    )

let groupByRequest (obs:IObservable<HistoryBar>) = 
    let bars = obs.GroupByUntil((fun x -> x.RequestId), (fun x -> x.Where(fun y -> y.Index = y.Total - 1)))
    bars.SelectMany(fun (x:IGroupedObservable<int, HistoryBar>) -> x.ToArray())

let obs = transformBar |> groupByRequest

client.RequestHistoricalData(1, sym, DateTime.Now, TimeSpan.FromDays(10.0), BarSize.OneDay, HistoricalDataType.Midpoint, 0)

如果我订阅了obs,那么只要我打电话给client.RequestHistoricalData,一切正常。我想做的是将obs转换为基础类型,在本例中为HistoryBar []。我尝试过使用waitToEnumberable但没有运气。这里有什么方法来提取我最后创建的数据?

编辑,添加人为的C#示例代码,以显示库通常如何工作。我真正想要了解的是如何从可观察到标准列表或数组。我不确定的是,如果我需要一个可变结构才能这样做。如果我不得不猜我会说不。

static void Main(string[] args)
{
...
client.HistoricalData += client_HistoricalData;
client.RequestHistoricalData(1, sym, DateTime.Today, TimeSpan.FromDays(10), BarSize.OneDay, HistoricalDataType.Midpoint, 0);
....
}

static void client_HistoricalData(object sender, HistoricalDataEventArgs e)
{

Console.WriteLine("Open: {0}, High: {1}, Low: {2}, Close: {3}, Date: {4}, RecordId: {5}, RecordIndex: {6}", e.Open, e.High, e.Low, e.Close, e.Date, e.RequestId, e.RecordNumber);
}

1 个答案:

答案 0 :(得分:2)

问题并不是很清楚如何首先加载数据(无论是懒惰/时变等)所以我只是假设它是一个有时间限制的值流。

从您的代码中,您似乎想要在流完成时找到流中的最后一个值。 Last方法为您提供流完成时推送的最后一个值 - 但这是同步的并阻塞直到流完成。非阻塞版本LastAsync返回一个Observable,它在源完成时生成一个值。

let from0To4 = 
    Observable.Interval(TimeSpan.FromSeconds(0.1)).Take(5)

let lastValue =
    from0To4.LastAsync()

let disposable =
    lastValue |> Observable.subscribe(log)

要将Observable转换为不阻塞的列表,您可以使用Buffer方法。要缓冲所有值,直到Observable完成,请使用ToList

let fullBuffer =
    from0To4.ToList()

let disposable =
    fullBuffer |> Observable.subscribe(fun ls -> printfn "Buffer(%d): %A" ls.Count ls)

输出:

  

缓冲液(5):seq [0L; 1L; 2L; 3L; ...]