WPF学习笔记(5)——WPF+Stylet+MVVM:通过线程实现进度条的动态加载,解决UI阻塞问题

问题描述

在winform中,如果要执行一个耗时操作,通常会使用进度条ProgressBar来显示耗时操作的进度,在winform中耗时操作的同时更改进度条的值,在UI上面可以看到进度条动态增长。
但是在WPF中(Stylet框架+MVVM开发模式),如果用同样的方法去实现,则会造成UI阻塞,进度条卡死,当耗时操作执行完毕后UI才刷新(参考下图)。
在这里插入图片描述

为什么会这样?

先看一下ViewModel
ViewModel定义了用于表示耗时操作进度的两个属性以及耗时操作,这些属性或者方法会在View中被绑定。

using Stylet;
using System.Threading;

namespace StyletTest.ViewModel
{
    public class ProgressBarViewModel:Screen
    {
        IWindowManager _windowManager;

        // 属性:当前值
        private int _nowValue;
        public int NowValue
        {
            get
            { return _nowValue; }
            set
            { SetAndNotify(ref _nowValue, value); }
        }

        // 属性:最大值
        private int _maxValue;
        public int MaxValue
        {
            get { return _maxValue; }
            set { SetAndNotify(ref _maxValue, value); }
        }

        // 构造函数
        public ProgressBarViewModel(IWindowManager windowManager)
        {
            _windowManager = windowManager;
        }
		
		// 事件
        public void StartLongTimeOperation()
        {
            // 执行模拟耗时操作
            LongTimeOperation();
        }

        // 模拟耗时操作
        private void LongTimeOperation()
        {
            // 设置最大值和当前值
            MaxValue = 30;
            NowValue = 0;

            for(int i = 1; i<= MaxValue; i++)
            {
                // 进度条的当前值递增
                NowValue = i;
                // 挂起一小会
                Thread.Sleep(100);
            }
            System.Windows.MessageBox.Show("耗时操作执行完毕");
        }

    }
}

再看一下View
在这里插入图片描述

<Window
    x:Class="StyletTest.View.ProgressBarView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:StyletTest.View"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:s="https://github.com/canton7/Stylet"
    Title="耗时操作"
    Width="400"
    Height="150"
    mc:Ignorable="d">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Button
            Grid.Row="0"
            Grid.Column="0"
            Grid.ColumnSpan="2"
            Command="{s:Action StartLongTimeOperation}"
            Content="开始执行耗时操作" />
        <Label
            Grid.Row="1"
            Grid.Column="0"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Content="当前值:" />
        <Label
            Grid.Row="1"
            Grid.Column="1"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Content="{Binding NowValue}" />
        <Label
            Grid.Row="2"
            Grid.Column="1"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Content="{Binding MaxValue}" />
        <Label
            Grid.Row="2"
            Grid.Column="0"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Content="最大值:" />
        <ProgressBar
            Grid.Row="3"
            Grid.Column="0"
            Grid.ColumnSpan="2"
            Maximum="{Binding MaxValue}"
            Value="{Binding NowValue}" />
    </Grid>
</Window>

正常上觉得这样在逻辑上行得通,预期效果应该是随着耗时操作的进行,进度条会跟着增长,但是UI却卡死了。
在这里插入图片描述
凡事儿不懂问百度,通过查阅,原因大致是这样的:耗时操作在UI线程中,阻塞了UI线程

解决方案

为耗时操作开启一条新的线程,线程去影响属性值!
代码修改:修改耗时操作(方法)的调用启动方式,开启一个新线程
在这里插入图片描述
在这里插入图片描述
整体思路
在这里插入图片描述

个人学习过程中解决遇到的问题的记录,如有错误烦请指正。

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

打赏
文章很值,打赏犒劳作者一下
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页

打赏

小顾爱编程

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者