.net – WPF的F#异步事件处理程序类似于C#的异步和等待

.net – WPF的F#异步事件处理程序类似于C#的异步和等待,第1张

概述如何在F#中编写异步 WPF(或 Windows窗体)事件处理程序?具体来说,是否有任何编码模式接近C#5的异步并等待? 这是一个完整的C#WPF应用程序: using System;using System.Threading;using System.Threading.Tasks;using System.Windows;using System.Windows.Controls; 如何在F#中编写异步 WPF(或 Windows窗体)事件处理程序?具体来说,是否有任何编码模式接近C#5的异步并等待?

这是一个完整的C#WPF应用程序:

using System;using System.Threading;using System.Threading.Tasks;using System.windows;using System.windows.Controls;class Program{    static int IncrementSlowly(int prevIoUs)    {        Thread.Sleep(3000);        if (prevIoUs == 2) throw new Exception("Oops!");        return prevIoUs + 1;    }    static async voID btn_Click(object sender,RoutedEventArgs e)    {        var btn = sender as button;        btn.IsEnabled = false;        try        {            var prev = (int)btn.Content;            btn.Content = await Task.Run(() => IncrementSlowly(prev));        }        catch (Exception ex)        {            btn.Content = ex.Message;        }        finally        {            btn.IsEnabled = true;        }    }    [STAThread]    static voID Main(string[] args)    {        var btn = new button() { Content = 0 };        var win = new Window() { Content = btn };        btn.Click += btn_Click;        new Application().Run(win);    }}

我无法弄清楚使用F#的等价物.我使用异步工作流和异步方法的组合进行了多次尝试.它真的很快就真的很乱.我希望有一个简单的方法,我只是俯瞰.

这是我的起点,它将UI锁定在btn.Content< - incrementSlowly prev.接下来我该怎么办?

open Systemopen System.Threadingopen System.Threading.Tasksopen System.windowsopen System.windows.Controlslet incrementSlowly prevIoUs =     Thread.Sleep(3000)    if prevIoUs = 2 then failwith "Oops!"    prevIoUs + 1let btn_Click (sender : obj) e =     let btn = sender :?> button    btn.IsEnabled <- false    try         try             let prev = btn.Content :?> int            btn.Content <- incrementSlowly prev        with ex -> btn.Content <- ex.Message    finally        btn.IsEnabled <- true[<EntryPoint>][<STAThread>]let main _ =     let btn = new button(Content = 0)    let win = new Window(Content = btn)    btn.Click.AddHandler(RoutedEventHandler(btn_Click))    Application().Run(win)

顺便说一下,假设incrementSlowly不能被修改.

解决方法 第一步是使incrementSlowly异步.这在C#代码中实际上是同步的,这可能不是一个好主意 – 在实际场景中,这可能是与网络通信,因此通常这实际上可以是异步的:
let incrementSlowly prevIoUs = async {  do! Async.Sleep(3000)  if prevIoUs = 2 then failwith "Oops!"  return prevIoUs + 1 }

现在,您可以使按钮单击处理程序也异步.我们稍后将使用Async.StartImmediate启动它以确保我们可以访问UI元素,因此我们现在不必担心调度程序或UI线程:

let btn_Click (sender : obj) e = async {  let btn = sender :?> button  btn.IsEnabled <- false  try     try       let prev = btn.Content :?> int      let! next = incrementSlowly prev      btn.Content <- next    with ex -> btn.Content <- ex.Message  finally    btn.IsEnabled <- true }

最后一步是更改事件注册.像这样的东西应该做的伎俩:

btn.Click.Add(RoutedEventHandler(fun sender e ->  btn_Click sender e |> Async.StartImmediate)

关键是Async.StartImmediate启动异步工作流程.当我们在UI线程上调用它时,它确保所有实际工作都在UI线程上完成(除非您明确地将其卸载到后台),因此可以安全地访问代码中的UI元素.

总结

以上是内存溢出为你收集整理的.net – WPF的F#异步事件处理程序类似于C#的异步和等待全部内容,希望文章能够帮你解决.net – WPF的F#异步事件处理程序类似于C#的异步和等待所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1251915.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存