F#Winforms图表异步更新

时间:2015-03-31 01:43:26

标签: multithreading winforms asynchronous f# f#-charting

我试图在winforms中创建一个图表,该图表数据绑定到内存中的列表,并在列表更改时动态更新。这是我的代码:

open System
open System.Linq
open System.Collections
open System.Collections.Generic
open System.Drawing
open System.Windows.Forms
open System.Windows.Forms.DataVisualization
open System.Windows.Forms.DataVisualization.Charting

let link = new LinkedList<double>()
let rnd = new System.Random()
for i in 1 .. 10 do link.AddFirst(rnd.NextDouble()) |> ignore
let series = new Series()
let chart = new System.Windows.Forms.DataVisualization.Charting.Chart(Dock = DockStyle.Fill, Palette = ChartColorPalette.Pastel)

series.Points.DataBindY(link)

let form = new Form(Visible = true, Width = 700, Height = 500)
form.Controls.Add(chart)

let formloop = async {
    while not chart.IsDisposed do
        link.AddFirst((new System.Random()).NextDouble()) |> ignore
        link.RemoveLast()
}
do
    Async.StartImmediate(formloop)
    Application.Run(form)

Console.WriteLine("Done")
Console.ReadLine() |> ignore

异步似乎有效,但图表从未显示任何内容。它只显示一个空白窗口。我做错了什么?

2 个答案:

答案 0 :(得分:4)

LinkedList<T>无法表明它已被更新,因此Chart无法知道何时重绘自己。

为了使数据绑定更新视图,源列表必须实现IBindingList并在内容更改时引发适当的事件。

另外,我必须指出,从非UI线程(例如代码中的chart.IsDisposed)直接访问UI属性/方法是危险的。在WinForms中,这种限制实际上很少被强制执行,因此有时这似乎可以正常工作,但以后只能在客户机器上崩溃而无法附加调试器。

答案 1 :(得分:1)

  • 您需要将系列添加到图表的SeriesCollection

    chart.Series.Add series
    
  • 您需要构建一个图表区域并将其添加到图表的ChartAreaCollection

    let area = new ChartArea()
    chart.ChartAreas.Add area
    
  • 您需要确保在设置图表和表单后调用数据绑定方法。

    ...
    form.Controls.Add chart
    series.Points.DataBindY link
    
  • 现在没有办法将绑定集合的更改传达给系列的DataPointCollection,如Fyodor Soikin's answer中所述。我不太确定IBindingList是否是恰当的回应; 虽然它可以挂钩ListChanged事件,但我们也可以操纵系列&#39;直接DataPointCollection

    let formloop = async{
        while not chart.IsDisposed do
            series.Points.RemoveAt 0
            series.Points.AddY(rnd.NextDouble()) |> ignore
            do! Async.Sleep 100 }
    
  • 最后,我想指出约翰·阿特伍德的这个contribution,其中论述了费奥多尔提出的两个观点;数据绑定问题(不使用它)和UI线程安全问题。