簡體   English   中英

F#STA線程異步

[英]F# STA Thread Async

我從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
  1. 使用[<STAThread>]

  2. 使用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)   
}

把等待放在一個額外的步驟,以保持其可組合。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM