首页 > 代码库 > 多线程

多线程

线程:简单的说就是找个工人来帮忙做事,线程启动时调用传过来的委托,委托就会执行相应的方法,实现线程执行方法.线程是程序的一个执行流,每个线程都有自己的专有寄存器(线指针,程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数.多线程是指程序中包含多个执行流,即在一个程序中可以同是运行多个不同的线程来执行不同的任务(代码),也就是说允许单个程序创建多个并执行的线程来完成各自的任务.
       进程与线程:一个进程(程序)至少有一个线程,一个进程中同时做多件事情就需要调用多个线程来完成事情,一个进程中的多个线程之间可以"并发"(来回快速切换)执行.
        前台线程:只有所有的前台线程都关闭才能完成程序的关闭,线程默认是前台线程.
        后台线程:只要所有的前台线程结束,后台线程自动结束.
         private void btnSingleThread_Click(object sender, EventArgs e)
        {
            //单线程的缺点:当运行程序做某件事时系统会启动一个默认的主线程也就是UI线程,
            //当主线程执行循环体时而不能"同时"做别的事情,当前的事情做完后才能做别的事情,所以要用到多线程减少时间.
            CountTime();//计数的方法;
        }
        /// <summary>
        /// 循环计数的方法
        /// </summary>
        void CountTime()
        {
            DateTime beginTime =DateTime.Now;//开始时间
            for (int i = 0; i < 1000000000; i++)
            {
            }
           TimeSpan ts = beginTime.Subtract(DateTime.Now);//开始时间到此时的间隔时间
           MessageBox.Show("循环完毕!!" + ts.Milliseconds);//间隔的毫秒数
        }
        //用多线程来"同时"(快速切换线程)做多件事情,帮助UI线程做事情从而解决UI卡死.
        private void btnMulThread_Click(object sender, EventArgs e)
        {
            ThreadStart ts = new ThreadStart(CountTime);//System.Threading线程的命名空间
            //创建线程对象,要传入执行的方法
            Thread threadFrist = new Thread(CountTime);//这是个无参数的方法
            //将前台线程设置为后台线程
            threadFrist.IsBackground = true;
            //启动线程,通过委托执行方法
            threadFrist.Start();
        }      
多线程方法重入问题
         void ChangeText() //修改文本框信息的方法
        {
            //多线程重入问题:当多个线程同时调用一个方法时,线程A还没有完全执行下面代码,线程B拿到线程A的值就开始执行了,
            //线程A同样没等线程B执行完下面代码就拿到线程B的值开始执行,直到循环结束.两线程都会执行100次循环,
            //也就是说虽然方法代码共用,但会各自单独的执行这个方法.
            for (int i = 0; i < 100; i++)
            {
                int b = int.Parse(txtName.Text); //这个文本框是由UI线程创建
                //每次循环打印当前运行的线程名及文本框中的值
                Console.WriteLine(Thread.CurrentThread.Name+"b="+b+"i="+i.ToString());
                b++;
               txtName.Text=b.ToString();
            }
        }
        private void btnProblem_Click(object sender, EventArgs e)
        {
            //ChangeText()UI线程自己访问可以通过(默认线程也是主线程)
            //自定义线程执行含UI线程创建的对象方法时会报异常TextBox.CheckForIllegalCrossThreadCalls = false;
            //停用捕获错误线程的属性
            Thread thread1 = new Thread(ChangeText);//创建线程对象,并标记该线程可以被CPU执行.
            thread1.Name = "c1";//给线程取名字
            thread1.IsBackground = true;//设定为后台线程.
            thread1.Start();//启动线程的方法
            Thread thread2 = new Thread(ChangeText);//第二个线程与第一个线程同时执行ChangeText()方法
            thread2.Name = "c2";
            thread2.IsBackground = true;//将前台线程设置为后台线程
            thread2.Start();
        }
带参数的方法线程是如何执行
        private void btnPrams_Click(object sender, EventArgs e)
        {
            //执行带参数的方法
            Thread threads = new Thread(txtTexts);//参数为null
            threads.IsBackground = true;//设为后台线程
            threads.Start(txtText.Text);//通过启动线程传objct类型的参数,
        }
        void txtTexts(object name)//传一个object类型的参数,线程执行的方法是object类型.
        {
            if (name!=null)//方法参数如不为就执行里面的代码
            {
                MessageBox.Show("name=" + name.ToString());//ToString()转换成字符串
            }
            else
            {
                MessageBox.Show(null);
            }  
        }     
带多个参数的方法线程又是如何执行
        void txtTexts(object name)//传一个object类型的参数,线程执行的方法是object类型.
        {
             //参数object类型所以可给name赋任何类型的数组集合,从而能通过构造方法为它赋初值。                                          

             List<string>list= name as  List<string>;
            if (name != null)//方法参数如不为就执行里面的代码
            {
                foreach ( string item in list)
                {
                    MessageBox.Show(item);//显示参数信息
                }
            }      
        }
        private void btnTemp_Click(object sender, EventArgs e)
        {
            Thread threads = new Thread(txtTexts);
            threads.IsBackground = true;//设为后台线程
            threads.Start(new List<string>(){"hong","you","hello" });//启动线程并通过构造方法传多个参数
        }