F# asynchronous event handlers for WPF similar to C#'s async and await

后端 未结 2 2028
礼貌的吻别
礼貌的吻别 2021-01-05 13:05

How does one code an asynchronous WPF (or Windows Forms) event handler in F#? Specifically, is there any coding pattern that approximates C# 5\'s async and await?

He

2条回答
  •  猫巷女王i
    2021-01-05 13:26

    Tomas correctly points out that if you can convert the slow method to be asynchronous, then let! and Async.StartImmedate work beautifully. That is preferred.

    However, some slow methods do not have asynchronous counterparts. In that case, Tomas's suggestion of Async.AwaitTask works too. For completeness I mention another alternative, manually managing the marshalling with Async.SwitchToContext.

    Async.AwaitTask a new Task

    let btn_Click (sender : obj) e = 
      let btn = sender :?> Button
      btn.IsEnabled <- false
      async {
        try 
          try 
            let prev = btn.Content :?> int
            let! next = Task.Run(fun () -> incrementSlowly prev) |> Async.AwaitTask
            btn.Content <- next
          with ex -> btn.Content <- ex.Message
        finally
          btn.IsEnabled <- true
      }
      |> Async.StartImmediate
    

    Manually manage thread context

    let btn_Click (sender : obj) e = 
      let btn = sender :?> Button
      btn.IsEnabled <- false
      let prev = btn.Content :?> int
      let uiContext = SynchronizationContext.Current
      async {
        try
          try
            let next = incrementSlowly prev
            do! Async.SwitchToContext uiContext
            btn.Content <- next
          with ex ->
            do! Async.SwitchToContext uiContext
            btn.Content <- ex.Message
        finally
          btn.IsEnabled <- true
      }
      |> Async.Start
    

提交回复
热议问题