当前位置:  编程技术>.net/c#/asp.net

浅解关于C#多线程的介绍

    来源: 互联网  发布时间:2014-10-18

    本文导语:  多线程的相关概念--------------------------------------------------------------------------------1.进程:是操作系统结构的基础;是一个正在执行的程序;计算机中正在运行的程序实例;可以分配给处理器并由处理器执行的一个实体;由单一顺...

多线程的相关概念
--------------------------------------------------------------------------------
1.进程:是操作系统结构的基础;是一个正在执行的程序;计算机中正在运行的程序实例;可以分配给处理器并由处理器执行的一个实体;由单一顺序的执行显示,一个当前状态和一组相关的系统资源所描述的活动单元。
2.线程:线程是程序中一个单一的顺序控制流程。是程序执行流的最小单元。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。
3.多线程:在单个程序中同时运行多个线程完成不同的工作,称为多线程。
--------------------------------------------------------------------------------
小结:其实更容易理解一点进程与线程的话,可以举这样一个例子:把进程理解成为一个运营着的公司,然而每一个公司员工就可以叫做一个进程。每个公司至少要有一个员工,员工越多,如果你的管理合理的话,公司的运营速度就会越好。这里官味一点话就是说。cpu大部分时间处于空闲时间,浪费了cpu资源,多线程可以让一个程序“同时”处理多个事情,提高效率。
--------------------------------------------------------------------------------
单线程问题演示
--------------------------------------------------------------------------------
创建一个WinForm应用程序,这里出现的问题是,点击按钮后如果在弹出提示框之前,窗体是不能被拖动的。

代码如下:

private void button1_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < 10000000000; i++) 
            {
                i += 1;
            }
            MessageBox.Show("出现后能拖动,提示没出现之前窗体不能被拖动");
        }

原因:运行这个应用程序的时候,窗体应用程序自带一个叫做UI的线程,这个线程负责窗体界面的移动大小等。如果点击按钮则这个线程就去处理这个循环计算,而放弃了其它操作,故而窗体拖动无响应。这就是单线程带来的问题。

解决办法:使用多线程,我们自己创建线程。把计算代码放入我们自己写的线程中,UI线程就能继续做他的界面响应了。
--------------------------------------------------------------------------------
线程的创建
--------------------------------------------------------------------------------

 线程的实现:线程一定是要执行一段代码的,所以要产生一个线程,必须先为该线程写一个方法,这个方法中的代码,就是该线程中要执行的代码,然而启动线程时,是通过委托调用该方法的。线程启动是,调用传过来的委托,委托就会执行相应的方法,从而实现线程执行方法。

代码如下:

//创建线程 
        private void button1_Click(object sender, EventArgs e)
        {
            //ThreadStart是一个无参无返回值的委托。
            ThreadStart ts = new ThreadStart(js);
            //初始化Thread的新实例,并通过构造方法将委托ts做为参数赋初始值。
            Thread td = new Thread(ts);   //需要引入System.Threading命名空间
            //运行委托
            td.Start();
        }
        //创建的线程要执行的函数。
        void js()
        {
            for (int i = 0; i < 1000000000; i++)
            {
                i += 1;
            }
            MessageBox.Show("提示出现前后窗体都能被拖动");
        }

把这个计算写入自己写的线程中,就解决了单线程中的界面无反应缺陷。
--------------------------------------------------------------------------------
小结:创建线程的4个步骤:1.编写线程索要执行的方法。2.引用System.Threading命名空。3.实例化Thread类,并传入一个指向线程所要运行方法的委托。4.调用Start()方法,将该线程标记为可以运行的状态,但具体执行时间由cpu决定。
--------------------------------------------------------------------------------
 方法重入(多个线程执行一个方法)
--------------------------------------------------------------------------------
 由于线程可与同属一个进程的其它线程共享进程所拥有的全部资源。

所以多个线程同时执行一个方法的情况是存在的,然而这里不经过处理的话会出现一点问题,线程之间先后争抢资源,致使数据计算结果错乱。

代码如下:

public partial class 方法重入 : Form
    {
        public 方法重入()
        {
            InitializeComponent();

            //设置TextBox类的这个属性是因为,开启ui线程,
            //微软设置检测不允许其它线程对ui线程的数据进行访问,这里我们把检测关闭,也就允许了其它线程对ui线程数据的访问。
            //如果检测不设置为False,则报错。
            TextBox.CheckForIllegalCrossThreadCalls = false;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            textBox1.Text = "0";
            //开启第一个线程,对js方法进行计算
            ThreadStart ts = new ThreadStart(js);
            Thread td = new Thread(ts);
            td.Start();

            //开启第二个线程,对js方法进行计算
            ThreadStart ts1 = new ThreadStart(js);
            Thread td1 = new Thread(ts1);
            td1.Start();
        }
        //多线程要重入的方法。
        void js()
        {
            int a = Convert.ToInt32(textBox1.Text);
            for (int i = 0; i < 2000; i++)
            {
                a++;
                textBox1.Text = a.ToString();
            }
        }
    }


出错现象:点击按钮后TextBox1中数据为2000+或2000,如果你看到的数据一直是2000说明你的计算机cpu比较牛X,这样的话你想看到不是2000的话,你可以多点击几次试试,真不行的话,代码中给TextBox1赋值为0,换做在界面中给textBox1数值默认值为0试试看。

出错原因:两个进程同时计算这个方法,不相干扰应该每个线程计算的结果都是2000的,但是这里的结果输出却让人以外,原因是第一个两个线程同时计算,并不是同时开始计算,而是根据cpu决定的哪个先开始,哪个后开始,虽然相差时间不多,但后开始的就会取用先开始计算过的数据计算,这样就会导致计算错乱。

解决办法:解决这个的一个简单办法解释给方法加锁,加锁的意思就是第一个线程取用过这个资源完毕后,第二个线程再来取用此资源。形成排队效果。

下面给方法加锁。

代码如下:

//多线程要重入的方法,这里加锁。
        void js()
        {
            lock (this)
            {
                int a = Convert.ToInt32(textBox1.Text);
                for (int i = 0; i < 2000; i++)
                {
                    a++;
                    textBox1.Text = a.ToString();
                }
            }
        }

给方法加过锁后,线程一前一后取用资源,就能避免不可预计的错乱结果,第一个线程计算为2000,第二个线程计算就是从2000开始,这里的结果就为4000。
--------------------------------------------------------------------------------
小结:多线程可以同时运行,提高了cpu的效率,这里的同时并不是同时开始,同时结束,他们的开始是由cpu决定的,时间相差不大,但会有不可预计的计算错乱,这里要注意类似上面例子导致的方法重入问题。
--------------------------------------------------------------------------------
 前台线程后台线程
--------------------------------------------------------------------------------
 .Net的公用语言运行时能区分两种不同类型的线程:前台线程和后台线程。这两者的区别就是:应用程序必须运行完所有的前台线程才可以退出;而对于后台线程,应用程序则可以不考虑其是否已经运行完毕而直接退出,所有的后台线程在应用程序退出时都会自动结束。

问题:关闭了窗口,消息框还能弹出。

代码如下:

private void button1_Click(object sender, EventArgs e)
        {
            //开启一个线程,对js方法进行计算
            ThreadStart ts2 = new ThreadStart(js);
            Thread td2 = new Thread(ts2);            
            td2.Start();

        }       
        void js()
        {
            for (int i = 0; i < 2000000000; i++)  //如果看不出效果这里的2后面多加0
            {
                i++;
            }
            MessageBox.Show("关闭了窗口我还是要出来的!");
        }


原因:.Net环境使用Thread建立线程,线程默认为前台线程。即线程属性IsBackground=false,而前台线程只要有一个在运行则应用程序不关闭,所以知道弹出消息框后应用程序才算关闭。

解决办法:在代码中设置td2.IsBackground=true;
--------------------------------------------------------------------------------
 线程执行带参数的方法
--------------------------------------------------------------------------------

代码如下:

//创建一个执行带参数方法的线程
        private void button1_Click(object sender, EventArgs e)
        {
            //ParameterizedThreadStart这是一个参数类型为object的委托
            ParameterizedThreadStart pts=new ParameterizedThreadStart(SayHello);
            Thread td2 = new Thread(pts);
            td2.Start("张三");  //参数值先入这里
        }
        void SayHello(object name)
        {
            MessageBox.Show("你好,"+name.ToString()+"!");
        }

 线程执行带多参数的方法
--------------------------------------------------------------------------------
 其实还是带一参数的方法,只不过是利用参数类型为object的好处,这里将类型传为list类型,貌似多参。
代码如下:

 //创建一个执行带多个参数的方法线程
        private void button1_Click(object sender, EventArgs e)
        {
            List list = new List { "张三", "李四", "王五" };
            //ParameterizedThreadStart这是一个参数类型为object的委托
            ParameterizedThreadStart pts=new ParameterizedThreadStart(SayHello);
            Thread td2 = new Thread(pts);
            td2.Start(list);  //参数值先入这里
        }
        void SayHello(object list)
        {
            List lt = list as List;
            for (int i = 0; i < lt.Count; i++)
            {
                MessageBox.Show("你好," + lt[i].ToString() + "!");
            }
        }

总结:看到这里相信对多线程应该有一个初步的了解了,我就不说了。

 


    
 
 

您可能感兴趣的文章:

  • c#多线程更新窗口(winform)GUI的数据
  • c# winform 关闭窗体时同时结束线程实现思路
  • c#多线程读取注册表 c#多线程的小例子
  • C#实现终止正在执行的线程
  • c#后台线程访问前台控件并显示信息示例
  • C#线程间不能调用剪切板的解决方法
  • C#实现线程池的简单示例
  • c# 多线程操作progressBar进度条控件的例子
  • C#子线程更新UI控件的方法实例总结
  • C#实现窗体与子线程的交互的方法
  • C#通过接口与线程通信(捕获线程状态)示例代码
  • C#利用子线程刷新主线程分享教程
  • 描述C#多线程中lock关键字的使用分析
  • C#中的多线程多参数传递详解
  • java线程之join方法的使用介绍 iis7站长之家
  • C# 多线程复制文件并显示进度条的代码
  • c#(asp.net)线程配置总结
  • c#线程同步的问题与实例分析
  • c#多线程中Lock()关键字的用法小结
  • c#钩子本线程内消息拦截的方法
  • c#线程间传递参数详解
  • Java中多线程相关类Thread介绍
  • 哪本书介绍mutex、POSIX 线程详解
  • Windows和Linux下C++类成员方法作为线程函数方法介绍
  • 帮忙介绍适合于SCO UNIX 5。05版本的多线程包的下载地址(最好是成功的安装过)
  • Linux下GCC内置原子操作函数(多线程资源访问)介绍
  • 哪位大牛可以介绍一下Linux2.6.xx以上版本内核是如何实现线程的吗?
  • python 多线程应用介绍
  • Java线程中sleep和wait的区别详细介绍
  • JAVA中 终止线程的方法介绍
  • java线程之join方法的使用介绍
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • c++的boost库多线程(Thread)编程(线程操作,互斥体mutex,条件变量)详解
  • 一个进程创建了两个线程,如何使得当任何一个线程(比如线程a)结束时,同时也结束线程b,也就是使两个线程一起死掉,怎么办呢?
  • java 线程,对当前线程(非主线程)调用sleep,为什么主线程(窗口)也没反应了
  • 如何实现一个线程组内多线程的非同不执行,即一个线程执行完毕后再执行下一个线程???
  • 请问:进程创建的线程是怎样运行的啊,线程的处理函数运行完了,线程就退出了吗?
  • 关于线程的问题,什么样的线程不是active线程?
  • 请问Linux核心支持多线程吗?开发库有线程库吗?线程好用吗?(稳定?)
  • 请问,在一个进程中创建多线程时如何能避免不同的线程获得同一个线程标识
  • 我的一个多线程服务里, 总是有一个线程莫名其妙的变成僵尸线程。
  • 能否通过线程id控制线程的状态?或是观察到线程的状态?
  • 如何在一个线程中启动另外一个线程,然后本线程就退出?
  • 我要设置一个线程的优先级, 这个属性结构并没有线程的id,它怎么知道是设置哪个线程呢?
  • 请问在java多线程中,是只有run(){}内的代码运行在一个新线程下呢?还是这个类中的代码都运行在一个新线程下?
  • gcc链接的库,分不分单线程版本的和多线程版本的?
  • 内核栈~ 内核线程 ~用户线程 之间关系 问题
  • 子线程的数据如何返回给主线程?
  • 如果父线程死掉 那么子线程会不会死掉呢
  • 多线程为何比单线程慢许多?
  • 如何设计线程池的监视线程
  • 大家来讨论一下,一个客户端一个线程好,还是线程池好?
  • main函数在线程执行完毕之前退出, 线程的哪些资源会被清理?


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3