zoukankan      html  css  js  c++  java
  • C#多线程案例基础

    在学习多线程之前,我们先来看几个概念:

    1,什么是进程?
        当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源,当然一个程序也可能开启多个进程
       而一个进程又是由多个线程所组成的。

    2.什么是线程?
       线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。

    3,什么是多线程?
       多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。

    多线程的好处:
       可以提高CPU的利用率。在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,这样就大大提高了程序的效率,当然也可以提升用户体验。多线程的      典型应用就是当从数据库中读取大量数据时,会造成界面假死,用户无法操作界面上的其他内容。而使用多线程就可以解决这个问题。 

    多线程的不利方面:
      线程也是程序,所以线程需要占用内存,线程越多占用内存也越多; 
      多线程需要协调和管理,所以需要CPU时间跟踪线程; 
      线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题;
      线程太多会导致控制太复杂,最终可能造成很多Bug;

    注意:任何程序在执行时,至少有一个主线程。

       一个程序从main开始之后,进程启动,为整个程序提供各种资源,而此时将启动一个线程,这个线程就是主线程,它将调度资源,进行具体的操作。Thread开启的线程是主线程下的子线程,是父子关系,此时该程序即为多线程的,这些线程共同进行资源的调度和执行。

    Thread类有几个至关重要的方法,描述如下:
       Start():启动线程;
       Sleep(int):静态方法,暂停当前线程指定的毫秒数; 
       Abort():通常使用该方法来终止一个线程;
       Suspend():该方法并不终止未完成的线程,它仅仅挂起线程,以后还可恢复; 
       Resume():恢复被Suspend()方法挂起的线程的执行;

       用通俗易懂的话来说,多线程可以让计算机"同时"做多件事情,节约时间。多线程可以让一个程序“同时”处理多个事情。

       下面我们通过几个案例来进一步了解多线程

    多线程的案例:

    案例1:通过多线程执行一个方法

    class Program

        {

            static void Main(string[] args)

            {

                MyClass myClass=new MyClass();

                Thread thread=new Thread(new ThreadStart(myClass.MyThread1));

                thread.Start();

                Console.WriteLine(thread.ThreadState);

                //注意这里用readline()不能用readkey否则不能出现效果

                Console.ReadLine();

            }

        }

        class MyClass

        {

             public void MyThread1()

             {

                 Console.WriteLine("大家好,我是线程1");

             }

        }

          解释下上述代码,首先在MyClass类中定义一个MyThread1方法,该方法无参数无返回值。然后在Main方法中,通过Thread类创建出一个Thread对象thread,但是其构造函数中需要传入一个委托变量,所以通过new ThreadStart(myClass.MyThread1)创建了一个委托变量,接下就可以通过thread.Start()启动线程,这里需要注意的是,调用thread的Start方法后,线程并不是马上执行,而仅仅是被标记为该线程可以执行了,至于线程何时执行,需要听从cpu的调度。

    案例2:带参数的线程启动方法

    static void Main(string[] args)

            {

                Thread thread=new Thread(new ParameterizedThreadStart(ParameterRun));

                string[] strs = {"李小龙","巩俐","范冰冰"};

                thread.Start(strs);

                Console.ReadLine();

            }

            static void ParameterRun(object obj)

            {

                Console.WriteLine("我是带参数的线程方法");

                string[] arr = obj as string[];

                foreach (string s in arr)

                {

                    Console.WriteLine(s);

                }

            }

         这个案例和案例1的唯一区别是创建Thread实例时需要一个带参数的委托变量作为构造函数的参数,而且符合委托规范的方法必须没有返回值,且只能有一个参数,并且参数类型是object的。ParameterRun方法参数赋值时,需要在thread.Start()中进行。

         当然,在真实的项目中,使用不可能这么简单,但是只要了解清楚了带参数线程的使用方式,再复杂的问题都会迎刃而解。

    案例3:模拟摇奖机程序

    public partial class Form1 : Form

        {

            public Form1()

            {

                InitializeComponent();

            }

            private Thread thread;

            //摇奖机是否为启动状态

            private bool isStart = false;

            private void btnok_Click(object sender, EventArgs e)

            {

                if (isStart)

                {

                    btnok.Text = "开始";

                    isStart = false;

                }

                else

                {

                    btnok.Text = "停止";

                    isStart = true;

                    //单独开启一个线程摇号,避免主线程假死

                    thread = new Thread(Show);

                    thread.Start();

                }

            }

            public void Show()

            {

                Random random=new Random();

                while (isStart)

                {

                    lbl1.Text = random.Next(0, 10).ToString();

                    lbl2.Text = random.Next(0, 10).ToString();

                    lbl3.Text = random.Next(0, 10).ToString();

                    //让当前线程睡一会儿

                    Thread.Sleep(100);

                }

            }

            private void Form1_Load(object sender, EventArgs e)

            {

                //不检查控件的跨线程操作

                Control.CheckForIllegalCrossThreadCalls = false;

            }

            private void Form1_FormClosing(object sender, FormClosingEventArgs e)

            {

                //在窗体关闭(主线程)前关闭子线程

                if (thread!=null)

                {

                    thread.Abort();

                }

            }

        }

      写该程序时,需注意几点:

    1,         在窗体的Load事件中设置不检查控件的跨线程操作

    2,         在主窗体关闭前,结束子线程的执行

    3,         为了避免随机数生活速度过快,使用Thread.Sleep(),让生成随机数的线程休息一段时间

    当然,我们讲解的只是多线程的使用方式,如果想要对多线程的底层实现有更深入的了解,还需查询更多书籍和资料。希望这篇文章能对您有所帮助。

    微冷的雨:2013-02-28日夜

    如若转载,请注明出处,微冷的雨出品---YYM
    注意 本文仅代表个人理解和看法哟!和本人所在公司和团体无任何关系!
  • 相关阅读:
    Configuration Management
    Android Hooking
    技术趋势总结
    Maven Repo Mirror
    拥抱JAVA
    NPM 更新所有依赖项
    Knockout Mvc Compoment FrameSet With Typescript
    Knockoutjs Component问题汇总
    前端编码规范文档
    优秀程序设计的18大原则
  • 原文地址:https://www.cnblogs.com/weilengdeyu/p/2937972.html
Copyright © 2011-2022 走看看