我从GUI线程中调用了这个函数:
let updateImageLoop (pprocess : PlotProcess) (target : IUpdatableImageView<'T>) =
async {
while target.Continue do
let context = System.Threading.SynchronizationContext.Current
do! Async.SwitchToThreadPool()
System.Threading.Thread.Sleep(10000)
do! Async.SwitchToContext(context)
let image = target.CreateImage()
match image with
| Some userImage -> do! target.UpdateImageView userImage
| None -> ()
} |> Async.StartImmediate
执行 target.UpdateImageView 方法时出现问题,生成异常:
调用线程必须是STA,因为许多UI组件都需要这个。
我知道,但这就是我用
做的事情do! Async.SwitchToContext(context)
消除SwitchToContext和SwitchToThreadPool函数,删除异常,但GUI只是冻结。这是有道理的,但为什么我不能在线程之间切换?
生成问题的函数是UpdateImageView。我测试它是否有异步。
member this.UpdateImageView etoimage =
async {
let imageview = new Eto.Forms.ImageView()
imageview.Image <- etoimage
this.Content <- imageview
}
编辑---
Testing with this code:
let updateImageLoop (pprocess : PlotProcess) (target : IUpdatableImageView<'T>) =
let context = System.Threading.SynchronizationContext.Current
let printThread text =
printfn "[%d] %s" System.Threading.Thread.CurrentThread.ManagedThreadId text
async {
while target.Continue do
printThread "begining"
do! Async.SwitchToThreadPool()
printThread "after swith to thread pool"
let image = target.CreateImage()
match image with
| Some userImage ->
printThread "before switch to context"
do! Async.SwitchToContext context
printThread "after switch to context"
target.UpdateImageView userImage
| None -> ()
} |> Async.StartImmediate
打印:
[1] begining
[4] after swith to thread pool
[4] before switch to context
[5] after switch to context
答案 0 :(得分:3)
使用[&lt; STAThread&gt;]
使用guiContext处理GUI
在GUI创建(框架初始化)中,记住guiContext
let guiContext = System.Threading.SynchronizationContext.Current
并将其传递给异步GUI执行
// the async GUI execute
async {
let currentContext = System.Threading.SynchronizationContext.Current
do! Async.SwitchToContext(guiContext)
f() // work on the GUI
do! Async.SwitchToContext(currentContext)
}
将等待放在一个额外的步骤以保持其可组合性。