• C#中的异步多线程7 WPF中的异步操作


    实际上异步方法在GUI程序中尤为有用,GUI程序在设计上就要求所有的现实变化都必须在GUI主线程上完成,比如点击按钮,展示标签,移动窗体等。Windows程序通过消息来实现这一点,消息会被放入由消息泵管理的消息队列中。

    消息泵从消息队列中取出一条信息,并调用它的处理程序(handler)代码。当处理程序代码完成时,消息泵获取下一条消息并循环这个过程。

    因为这种机制,处理程序就必须短小精悍,才不至于挂起并阻碍其他GUI行为的处理。如果某个消息的处理程序代码耗时过长,消息队列中的消息就会产生挤压,程序会失去响应,因为在哪个长时间运行的处理程序完成之前,无法处理其他任何消息。

    为了模拟一个长耗时的任务造成的影响,建立如下的WPF程序:

    <Window x:Class="MessagePump_AsyncSample.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <StackPanel>
            <Label Name="lblStatus" Margin="10,5,10,0">Not Doing Anything</Label>
            <Button Name="btnDoStuff" Content="Do stuff" HorizontalAlignment="Left" Margin="10,5" Padding="5,2" Click="btnDoStuff_Click"></Button>
        </StackPanel>
    </Window>
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private async void btnDoStuff_Click(object sender, RoutedEventArgs e)
            {
                btnDoStuff.IsEnabled = false;
                lblStatus.Content = "Doing Stuff";
                Thread.Sleep(4000);
                //await Task.Delay(4000);
                lblStatus.Content = "Not Doing Anything";
                btnDoStuff.IsEnabled = true;
            }

    用户点击按钮后:禁用按钮——将标签文本修改为Doing Stuff,这样用户会知道程序在运行——休眠4s,模拟长耗时任务——将标签改为原始文本,并启用按钮。

    但实际上,点击按钮后,什么也没有发生,4s内也不能移动窗体,4s后窗体才会出现在新位置。

    原因在于,点击按钮哦是,click消息放入消息队列,消息泵从队列中移除该信息并开始处理点击按钮的处理程序代码,即btnDoStuff_Click方法中的代码,btnDoStuff_Click将希望发生的行为放入队列(禁用按钮,改变文本,移动窗体,改变文本,恢复按钮),但在处理程序本身退出之前,这些消息都无法执行(4s),然后所有的行为都发生了,但速度太快看不到。

    但如果,处理程序能将前2条消息压入队列,然后将自己从处理器上摘下,4s后再压入队列,那么这些消息都可以在等待的时间内被处理,还能保持响应。

    async,await就可以做到,当到达await关键字时,处理程序返回到调用方法,并从处理器上摘下,这时其他消息得到,包括最初的2条记录,在空闲任务(Task.Delay)完成后,后续部分又重新被安排到线程上。

  • 相关阅读:
    数据库
    计算机基础知识系列
    《大话数据结构》参考
    数据结构与算法系列
    python cookbook
    Python教程 廖雪峰
    Python入门学习系列
    认识 React——声明式,高效且灵活的用于构建用户界面的 JavaScript 库
    线程---同步(synchronized)
    线程---插队和礼让执行(join和yield)
  • 原文地址:https://www.cnblogs.com/NicolasLiaoran/p/12939486.html
Copyright © 2020-2023  润新知