美文网首页
关于Dispatcher

关于Dispatcher

作者: Memoyu | 来源:发表于2019-04-20 00:26 被阅读0次

感谢[Jason_Yuan]原文来源于:[https://www.jianshu.com/p/0714fc755988]
个人浅知,用自己能看懂 的写一下,如有错误,请指教!谢谢!

对Dispatcher认知

首先,我们要对WPF应用中程序开启的时候是开启了一个进程,进程中至少两个线程:

一个线程用于呈现UI,隐藏于后台。
一个线程用于接受输入、处理事件等。即为UI线程。

而在UI线程中有一个Dispatcher对象,该对象的作用在于管理UI线程每个执行的工作项。根据每个工作的优先级排队,优先级可设置,有十个不同级别。Dispatcher队列工作项应保证小,保证个用户体验。

Dispatcher提供了两个注册工作项的方法:Invoke 和 BeginInvoke。

Invoke方法:这是个同步调用,就是要执行完这个注册对的工作项(执行完委托)才会返回。
BeginInvoke方法:这是个异步调用,即可返回。

解决的问题

我们在设计程序的的过程中总会涉及到某些耗时操作会占用主线程,造成程序假死,用户体验差,这种问题我们就要用到子线程去处理耗时操作,而子线程不能直接修改主线程(UI线程)创建的UI对象,必须通过向UI线程中的Dispatcher注册工作项来完成。如下例子中,我需要创建一个子线程去执行加载ProgressBar的操作,这是个耗时操作,如果置于主线程,则会造成假死。所以,我们需要子线程执行耗时操作。

例子代码

XAML
<Window x:Class="About_DispatherClass.MainWindow"
      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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:local="clr-namespace:About_DispatherClass"
      mc:Ignorable="d"
      Title="MainWindow" Height="250" Width="300">
  <StackPanel>
      <ProgressBar Name="schduleBar" Height="30" Width="250" Margin="20"></ProgressBar>
      <TextBox Name="scheduleNum" Height="20" Width="30" HorizontalAlignment="Center">0</TextBox>
      <Button Name="btnStart" Content="Start" Height="30" Width="100" Margin="10"></Button>
      <Button Name="btnCancel" Content="Cancel" Height="30" Width="100"></Button>
  </StackPanel>
</Window>

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace About_DispatherClass
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            btnStart.Click += BtnStart_Click;//注册按钮事件
            btnCancel.Click += BtnCancel_Click;
        }

        Thread threadStart;//声明线程

        /// <summary>
        /// 开始进度按钮事件
        /// </summary>
        private void BtnStart_Click(object sender, RoutedEventArgs e)
        {
            threadStart = new Thread(DoTask);//创建线程,去更新加载进度条信息及加载数具体数字
            threadStart.Start();
            /////////////////////////////////////////////
            //关闭线程。如果这样,程序则会假死
            //int maxValue = 100;
            //for (int i = 0; i < maxValue; i++)
            //{
            //    Thread.Sleep(100);//线程休眠 100ms
            //    this.Dispatcher.BeginInvoke((Action)delegate ()//向Dispatcher里注册工作方法
            //    {
            //        this.schduleBar.Value = i;
            //        this.scheduleNum.Text = i.ToString();
            //    });
            //}
            /////////////////////////////////////////////////
        }

        /// <summary>
        /// 取消进度按钮事件,恢复默认
        /// </summary>
        private void BtnCancel_Click(object sender, RoutedEventArgs e)
        {
            threadStart.Abort();//终止线程
            MessageBox.Show("取消加载,恢复默认", "提示");
            this.schduleBar.Value = 0;//清空
            this.scheduleNum.Text = null;
        }
        /// <summary>
        /// 新线程要做的事情,完成加载进度条,
        /// </summary>
        private void DoTask()
        {
            int maxValue = 100;
            for (int i = 0; i < maxValue; i++)
            {
                Thread.Sleep(100);//线程休眠 100ms
                this.Dispatcher.BeginInvoke((Action)delegate()//向Dispatcher里注册工作方法
                {
                    this.schduleBar.Value = i;
                    this.scheduleNum.Text = i.ToString();
                });
            }

            MessageBox.Show("加载完成,恢复默认","提示");
            this.Dispatcher.BeginInvoke((Action)delegate 
            {
                this.schduleBar.Value = 0;
                this.scheduleNum.Text = null;
            });
        }



    }
}

展示

假死.gif 子线程处理.gif

相关文章

网友评论

      本文标题:关于Dispatcher

      本文链接:https://www.haomeiwen.com/subject/unuhgqtx.html