1

有这个代码:

let errorChanged = new Event<(int * float)>()

let learn error data w w_ iter =
    let rec learning error data w w_ i icount =
        //recursive(loop) fire event
        errorChanged.Trigger(i, e) //trigger event for chart update
        if (/**/) then
            learning /*params*/
        else
            /*do else*/

    let plot = LiveChart.PointIncremental(errorChanged.Publish |> Event.every 5)
    plot.ShowChart()
    learning error data w w_ 0 iter

当我运行它时,我看到点图窗口,它没有响应(也没有更新)。根据代码示例,这应该可以正常工作,但是......我该如何解决这个问题?

更新

如果我做:

let rec learning error data w w_ i icount = async {
            let e = Seq.fold (fun s x ->
                                         s + errorPart w w_ x x) 0.0 data
            errorChanged.Trigger(i, e)
            if (e > error && i <= iter) then
                printfn "[iter] = %d of %d. [e] = %f" i icount e
                let (w, w_) = Seq.fold (fun (w, w_) x -> 
                                                learnPart w w_ x x) (w, w_) data
                return! learning error data (normalize w) (normalize w_) (i + 1) icount
            else
                let resultData = Seq.map (fun x -> calculatePart w w_ x) data
                let y = resultData
                        |> Seq.map (fun (y, _) -> y) 
                        |> Seq.concat
                let x_ = resultData
                        |> Seq.map (fun (_, x_) -> x_) 
                        |> Seq.concat
                return (w, w_, e, y, x_) }

        let plot = LiveChart.PointIncremental(errorChanged.Publish |> Event.every 5)
        plot.ShowChart()
        async { return! learning error data w w_ 0 iter}
        |> Async.RunSynchronously

我得到异常:跨线程操作无效。好像我需要类似的东西Dispatcher

4

2 回答 2

3

您的代码片段的问题在于它创建了图表,但随后它learning在当前线程上运行该函数,因此它阻塞了主线程(它永远没有机会更新图表)。

learning您可以将函数包装在async { .. }块中并使用Async.Start. 然后它将在后台运行并且图表将能够更新。

您没有发布完整的代码,所以我无法测试,但我认为以下应该可行:

let rec learning error data w w_ i icount = async { // Async block here!
    (* omitted *)
    errorChanged.Trigger(i, e) //trigger event for chart update
    if (e > error && i <= iter) then
        (* omitted *) 
        // Here, we now need to run the recursive call using 'return!' of async
        return! learning error data (normalize w) (normalize w_) (i + 1) icount
    else
        (* omitted *)
        return (w, w_, e, y, x_) }

let plot = LiveChart.PointIncremental(errorChanged.Publish |> Event.every 5)
plot.ShowChart()

// Create workflow that will run 'learning' and then print the result
// (this needs to return unit, so that we can use 'Async.Start')
async { let! res = learning error data w w_ 0 iter 
        printfn "Finished: %A" res } 
|> Async.Start
于 2013-10-29T20:30:39.470 回答
0

这可能是缺少WinForms 事件循环

试试这个简单的代码,看看它是否先挂起,然后将它应用到你的情节

use form = new Form(Width=400, Height=300, Visible=true, Text="Hello charting")
Chart.Line([for x in 0 ..10 -> x, x+x]).ShowChart()
System.Windows.Forms.Application.Run(form)
于 2014-07-15T19:40:30.760 回答