I call this this function from the GUI thread:
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
[<STAThread>]
属性吗? - kvbUpdateImageView
抛出的,可能它期望在创建图像的同一STA线程上调用?也就是说,你使用的库可能期望在同一线程上调用CreateImage
和UpdateImageView
。 - Wallace Kelly