码迷,mamicode.com
首页 > 编程语言 > 详细

[Aaronyang] 写给自己的WPF4.5 笔记16[多线程]

时间:2015-03-04 14:35:42      阅读:195      评论:0      收藏:0      [点我收藏+]

标签:

  =============潇洒的版权线==========www.ayjs.net===== Aaronyang ========= AY =========== 安徽 六安 杨洋 ==========   未经允许不许转载 =========

System.Windows.Threading.Dispatcher类(wpf新增的)

DispatcherObject类(Dispatcher,CheckAccess(),VerifyAccess())

具有线程关联性的WPF对象都在类层次的某个位置继承自DispatcherObject类。


 

demo1:普通线程方式

界面:

<Grid>
        <Button x:Name="btn1" Content="更新文本" HorizontalAlignment="Left" Margin="209,50,0,0" VerticalAlignment="Top" Width="75" Click="btn1_Click"/>
        <TextBox x:Name="tb1" HorizontalAlignment="Left" Height="23" Margin="26,50,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120"/>

    </Grid>

后台:

 private void btn1_Click(object sender, RoutedEventArgs e)
        {
            Thread t = new Thread(updateTxt);
            t.Start();
        }

        private void updateTxt()
        {
            Thread.Sleep(TimeSpan.FromSeconds(5));
            tb1.Text = "你好阳光";
        }

失败了

技术分享

updateTxt()方法在新线程上运行,不允许访问WPF对象。TextBox对象调用VerifyAccess()方法捕获异常。(aaronyang博客)

使用WPF方式将操作封送到调度程序线程即可

 private void updateTxt()
        {
            Thread.Sleep(TimeSpan.FromSeconds(5));
            //tb1.Text = "你好阳光";
            this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()
            {
                tb1.Text = "你好阳光";
            });
        }

此时拖动窗口也没有卡顿。5秒后自动更新界面。第一个参数是优先级。DispatcherPriority.SystemIdle表示CPU空闲状态。DispatcherPriority.ApplicationIdle应用程序空闲时候再操作。

BeginInvoke返回线程信息,可控制,也可以获得执行状态,我在前台加了个进度条

   private void updateTxt()
        {
            Thread.Sleep(TimeSpan.FromSeconds(5));
            //tb1.Text = "你好阳光";
            //this.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, (ThreadStart)delegate()
            //{
            //    tb1.Text = "你好阳光";
            //});

            //可用于判断是否完成
            var dispatcherOperation = this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()
            {
                Thread.Sleep(TimeSpan.FromSeconds(5));
                tb1.Text = "你好阳光";
            });
            while (!(dispatcherOperation.Status==DispatcherOperationStatus.Completed))
            {
               
             }
            this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()
            {
                pb1.Value = 100;
            });

        }

Invoke是同步的方法,BeginInvoke是异步的。


 

System.ComponentModel.BackgroundWorker类

还提供了进度事件和取消消息,由于BackgroundWorker不可见,所以声明在窗口的资源里面,我们需要引入空间

<Window x:Class="multhread.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:cm="clr-namespace:System.ComponentModel;assembly=System"
        Title="MainWindow" Height="350" Width="525">

DEMO2

   <Window.Resources>
        <cm:BackgroundWorker x:Key="bw" WorkerReportsProgress="True" WorkerSupportsCancellation="True"
            DoWork="BackgroundWorker_DoWork" RunWorkerCompleted="BackgroundWorker_RunWorkerCompleted" ProgressChanged="BackgroundWorker_ProgressChanged"
                             ></cm:BackgroundWorker>
    </Window.Resources>

后台获得

 private BackgroundWorker bw;
        public int sum = 0;
        public MainWindow()
        {
            InitializeComponent();
            bw = (BackgroundWorker)this.FindResource("bw");
        }

OK,接下来我们来做个后台耗时的操作,我们使用Thread模拟吧,前台定义好界面

<Window x:Class="multhread.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:cm="clr-namespace:System.ComponentModel;assembly=System"
        Title="从1加到10 aaronyang demo" Height="350" Width="525">
    <Window.Resources>
        <cm:BackgroundWorker x:Key="bw" WorkerReportsProgress="True" WorkerSupportsCancellation="True"
            DoWork="BackgroundWorker_DoWork" RunWorkerCompleted="BackgroundWorker_RunWorkerCompleted" ProgressChanged="BackgroundWorker_ProgressChanged"
                             ></cm:BackgroundWorker>
    </Window.Resources>
    <Grid>
        <Button x:Name="btn1" Content="开始增加" HorizontalAlignment="Left" Margin="21,70,0,0" VerticalAlignment="Top" Width="75" Click="btn1_Click" IsEnabled="true"/>
        <Button x:Name="btn2" Content="取消增加" HorizontalAlignment="Left" Margin="101,70,0,0" VerticalAlignment="Top" Width="75" Click="btn2_Click" IsEnabled="False"/>

        <TextBox x:Name="tb1" HorizontalAlignment="Left" Height="23" Margin="76,10,0,0" TextWrapping="Wrap" Text="10" VerticalAlignment="Top" Width="120"/>
        <ProgressBar x:Name="pb1" HorizontalAlignment="Left" Height="16" Margin="21,108,0,0" VerticalAlignment="Top" Width="289" Maximum="100" Minimum="0"/>
        <Label Content="目标分数" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/>
        <Label Content="当前分数:" HorizontalAlignment="Left" Margin="10,40,0,0" VerticalAlignment="Top"/>
        <Label x:Name="lblPoint" Content="0" HorizontalAlignment="Left" Margin="78,39,0,0" VerticalAlignment="Top" RenderTransformOrigin="0,-0.2"/>

    </Grid>
</Window>

技术分享

后台看代码没啥解释的。

  /// <summary>
        /// 开始线程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn1_Click(object sender, RoutedEventArgs e)
        {
            //Thread t = new Thread(updateTxt);
            //t.Start();
            btn1.IsEnabled = false;
            btn2.IsEnabled = true;
            int grade=Convert.ToInt32(tb1.Text);
            bw.RunWorkerAsync(grade);

        }

然后开始了Dowork的方法

  private void BackgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            int max = (int)e.Argument;
            long c = 0;
            for (int i = 1; i <= max; i++)
            {
                System.Threading.Thread.Sleep(TimeSpan.FromMilliseconds(200));//每完成1次相当于10%
                c = c + i;
                bw.ReportProgress(i * 10);
            }
            e.Result = c;
        }

dowork完以后,会返回最终结果,我们在Completed中显示结果

  private void BackgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message);
            }
            else {
                lblPoint.Content = e.Result.ToString();
            }
        }

我们在dowork时候,调用ReportProgress报告进度

   private void BackgroundWorker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
        {
            pb1.Value = e.ProgressPercentage;
        }

取消线程

   //取消线程
        private void btn2_Click(object sender, RoutedEventArgs e)
        {
            bw.CancelAsync();
        }

然后,在dowork中判断,是否取消,如果取消就结束。

   private void BackgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            int max = (int)e.Argument;
            long c = 0;
            for (int i = 1; i <= max; i++)
            {
                if (bw.CancellationPending) {
                    e.Cancel = true;
                    return;
                }
                System.Threading.Thread.Sleep(TimeSpan.FromMilliseconds(500));//每完成1次相当于10%
                c = c + i;
                bw.ReportProgress(i * 10);
            }
            e.Result = c;
        }

        private void BackgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                //MessageBox.Show("操作已经取消");
                pb1.Value = 0;
                btn1.IsEnabled = true;
                btn2.IsEnabled = false;
                return;
            }
            else {
                if (e.Error != null)
                {
                    MessageBox.Show(e.Error.Message);
                }
                else
                {
                    lblPoint.Content = e.Result.ToString();
                }
                btn1.IsEnabled = true;
                btn2.IsEnabled = false;
            }
        
           
           
        }

效果图:

技术分享


 

这个简单的DEMO就先当这里了

  =============潇洒的版权线==========www.ayjs.net===== Aaronyang ========= AY =========== 安徽 六安 杨洋 ==========   未经允许不许转载 =========

-------------------小小的推荐,作者的肯定,读者的支持。推不推荐不重要,重要的是希望大家能把WPF推广出去,别让这么好的技术消失了,求求了,让我们为WPF技术做一份贡献。------

 

[Aaronyang] 写给自己的WPF4.5 笔记16[多线程]

标签:

原文地址:http://www.cnblogs.com/AaronYang/p/4313202.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!