VB.net 2010 视频教程 VB.net 2010 视频教程 VB.net 2010 视频教程
  • 从WPF入手,实现简单的多线程

  • 2016-12-06 23:32 来源:未知
从WPF入手,实现简单的多线程
WPF入手,实现简单的多线程 
此贴接昨天发的笔记,这次我了解了WPF的多线程大致实现原理,并简单编写了一个多线程程序。 
先将几个常用的概念列一下:
线程关联度:WPF属于创建它的线程,并且不能被其他的线程直接访问。当一个对象被关联到一个单线程时,就认为它是一个单线程对象,并且认为该对象具有线程关联度。
同步:同步可以理解为在执行完一个函数或方法之后,一直等待系统返回值或消息,这时程序是出于阻塞的,只有接收到返回的值或消息后才往下执行其他的命令。 这样的好处是能避免读写时的数据错误。
异步:执行完函数或方法后,不必阻塞性地等待返回值或消息,只需要向系统委托一个异步过程。在此期间可以进行别的过程,当系统接收到之前那个调用的返回值或消息时,系统会自动触发委托,开始处理返回值。
下面以两段WPF的代码为例,说明如何利用委托来实现异步线程,我使用的是Visual Studio 2008
第一段代码
前台代码
<Window x:Class="ThreadTest.Window1"
    xmlns="//schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="//schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <Border Width="200" Height="225" BorderBrush="Black" BorderThickness="1" Margin="4">
            <StackPanel>
                <TextBox Height="19" Name="textBox1" VerticalAlignment="Top" />
                <Button HorizontalAlignment="Left" Name="button1" Width="75" Click="button1_Click">Button1</Button>
                <Button HorizontalAlignment="Left" Name="button2" Width="75" Click="button2_Click">Button2</Button>
                <Label Height="28" Name="UIThreadId" Width="120" Content=""/>
            </StackPanel>
        </Border>
    </Grid>
</Window> 
 后台代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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;
using System.Threading;

namespace ThreadTest
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            this.UIThreadId.Content = this.Dispatcher.Thread.ManagedThreadId;
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            this.textBox1.Text = "Sleeping";
            Thread.Sleep(5000);
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            this.textBox1.Text = "Hello WPF";
        }
    }
}
 
     这段代码中,button1调用的过程中由于Sleep(5000)的存在,一直占用着线程,此时我们可以发现,按button2不会有反应,因为WPF的UI默认的是单线程模式(STA)。只有当原来的函数退出线程了,第二个函数才会进入线程,更改textbox里的内容。
 
    要想让UI能自由的变化,首先我们要为另一个函数另开一个线程,之后我们使用委托和分发器(Dispatcher)来实现另一个线程中的函数对主线程中UI的更改??梢运?,使用分发器的过程,就是我们实现异步线程的过程。
 
    那么委托和分发器又是如何实现异步线程的呢?
我的理解是:分发器的作用在于给不同线程的函数安排执行的顺序。委托相当于函数的包装,让这些函数过程可以被包装进入分发器等候调遣。比喻可能不大恰当,欢迎指正^_^
这样,在不同线程上的函数可以被分发器统一调度、执行,执行完后有了返回值,再触发处理返回值的委托,不断进行下去。
下面以代码为例,说明异步线程的产生。
第二段代码:
 前台代码
<Window x:Class="MutipleThreads.Window1"
    xmlns="//schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="//schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <Border Width="200" Height="225" BorderBrush="Black" BorderThickness="1" Margin="4">
            <StackPanel>
                <TextBox Height="19" Name="textBox1" VerticalAlignment="Top" />
                <Button HorizontalAlignment="Left" Name="button1" Width="75" Click="button1_Click">Button1</Button>
                <Button HorizontalAlignment="Left" Name="button2" Width="75" Click="button2_Click">Button2</Button>
            </StackPanel>
        </Border>
    </Grid>
</Window>
 
后台代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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;
using System.Windows.Threading;
using System.Threading;

namespace MutipleThreads
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        private delegate void ThreadDelegate(); //申明一个专用来调用更改线程函数的委托

        public Window1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            ThreadDelegate backWorkDel = new ThreadDelegate(prcessStart); //创建一个ThreadDelegate的实例,调用准备在后台运行的函数
            backWorkDel.BeginInvoke(null, null);//使用异步的形式开始执行这个委托
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            this.textBox1.Text = "Awake";   //主线程中更改界面,不要别的代码
        }

        private void prcessStart()          //这个就是我们将要在后台执行的函数
        {
            ThreadDelegate changeTetBoxDel = delegate()  //后台中要更改主线程中的UI,于是我们还是用委托来实现,再创建一个实例
            {
                this.textBox1.Text = "Sleeping";
            };//要调用的过程
            this.Dispatcher.BeginInvoke(DispatcherPriority.Send, changeTetBoxDel); //使用分发器让这个委托等待执行

            Thread.Sleep(3000);
        }
        
    }
}
 
    还是两个按钮,都要更改textbox1的内容,不同的是当按下Button1时,我们不是直接更改其内容,而是另外开了一个线程,并指明以异步方式运行。这样更改UI的函数就在另一个线程里运行了。但是问题又来了,WPF规定,UI只能被主线程所访问,那么在另一个线程中的prcessStart()如何更改UI呢?我们用Dispatcher和委托来实现,先实例化委托,在为其委托创建好要调用的过程,再使用分发器让它等待执行。DispatcherPriority.Send是我们为其规定的优先级。
      运行后可以发现界面可以自由的更改。 这就是多线程的作用。
      一般来说,我们都会把需要不断运算而很少改动界面的过程作为后台运行,从而解放出前台的线程来和用户交互。
对自己的这种初学者很有用,文章转自//lywzn.blog.sohu.com/157756036.html
 
相关教程
  • 【砥砺奋进的5年】空气质量优良 "南宁蓝"常驻绿城 2019-02-17
  • 机关党建工作巡礼——广东“走前头作表率” 2019-02-17
  • 为什么说一直辛苦劳作的农民没有富起来?而不说一直勤劳的农民没有富起来? 2019-02-17
  • 中欧美六国商会签约 国际战略合作在石达成 2019-02-17
  • 【专题】走龙江丝路 向北看发展 华南城 全国重点网媒龙江集中采访活动 2019-02-16
  • 彩民复式追加投注 斩获体彩大乐透1425万 2019-02-16
  • 多彩课堂熔铸红色魂——甘祖昌干部学院教学素描 2019-02-16
  • 张佳宁杂志玩转新娘风 甜系女生展俏皮魅力 2019-02-15
  • 中央调剂制度促进养老保险制度可持续发展 2019-02-15
  • 西安高科工程技术学校——陕西省政府直属中等职业院校西安高科工程技术学校2018招生简章-陕西教育新闻 2019-02-14
  • 旅游低价团暗藏玄机 治理需保持高压态势--旅游频道 2019-02-14
  • 【高清】傈僳族乡村女教师熊文碧:背着娃娃教书 2019-02-13
  • QS世界大学排名发布:中国11所大学进百强,清华排名创历史 2019-02-13
  • 辽宁贯彻十九大精神:领导沉下去 群众用心学 2019-02-13
  • 多部门三令五申禁网售彩票,世界杯竞猜APP上仍热卖 2019-02-12
  • 338| 688| 115| 648| 912| 109| 50| 356| 773| 793|