【问题标题】:F# Winforms Charting Asynchronous UpdatingF# Winforms 图表异步更新
【发布时间】:2015-06-04 05:40:15
【问题描述】:

我正在尝试在 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

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

【问题讨论】:

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


    【解决方案1】:

    LinkedList&lt;T&gt; 无法发出已更新的信号,因此Chart 无法知道何时重绘自己。

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

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

    【讨论】:

      【解决方案2】:
      • 您需要将系列添加到图表的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 事件,但我们也可以直接操纵系列的DataPointCollection

        let formloop = async{
            while not chart.IsDisposed do
                series.Points.RemoveAt 0
                series.Points.AddY(rnd.NextDouble()) |> ignore
                do! Async.Sleep 100 }
        
      • 最后,我想指出 John Atwood 的 contribution,它解决了 Fyodor 提出的两个问题;数据绑定问题(不使用它)和 UI 线程安全问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-04-04
        • 2017-06-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多