Диаграмма (Fsharp.Charting) не отвечает
Имея этот код:
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
когда я запускаю его, я вижу окно Point Chart, которое не отвечает (и не обновляется). В соответствии с примерами кода это должно работать хорошо, но... Как я могу это исправить?
UPD:
если я сделаю:
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
,
2 ответа
Проблема с вашим фрагментом кода в том, что он создает диаграмму, но затем запускает 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
Это, вероятно, отсутствие цикла событий 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)