.NET基础-16-多线程

多线程
        public Form1()
        {
            InitializeComponent();

            //每一个应用程序都是一个进程
            //每个进程有一个以上的线程组成

            ////获取当前电脑所有的进程
            //Process[] pro = Process.GetProcesses();
            ////循环输出所有的进程信息
            //foreach (var item in pro)
            //{
            //    //杀死所有进程
            //    //item.Kill();//会蓝屏的
            //    Console.WriteLine(item);
            //}

            ////获取当前正在运行的系统的进程信息
            //Process curr = Process.GetCurrentProcess();
            //Console.WriteLine(curr);
            ////关闭该进程
            ////curr.Kill();

            //Process.Start("calc");//启动计算器
            //Process.Start("mspaint");//启动画图
            //Process.Start("iexplore", "http://www.baidi.com");//启动IE
            //Process.Start("firefox", "http://www.baidi.com");//启动IE
            //Process.Start("devern");//启动vs

            Control.CheckForIllegalCrossThreadCalls = false;
        }

        /// <summary>
        /// 单线程直接调用打印输出方法Test
        /// 因为该方法会耗费大量的时间
        /// 在该方法执行完成之前进程都会在处理该方法
        /// 从而导致程序出现假死现象,导致程序无法进行其他的任何操作
        ///
        /// 程序在启动之后会产生一个主线程,在没有调用Test方法前,主线程来可以来处理窗体拖动,最大化,最小化等操作
        /// 但是一旦Test开始执行,则主线程就用来处理Test方法内的操作
        /// 而此时拖动窗体的时候就需要等主线程执行完Test方法之后空闲下来才可以执行拖动窗体操作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            //单线程直接调用Test方法
            Test();
        }

        /// <summary>
        /// 多线程调用Test方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            //创建一个线程去调用Test方法
            Thread th = new Thread(Test);

            //指定该线程为后台线程,关闭前台主线程的时候会立刻关闭后台线程
            //关闭界面的时候,就算改方法没有执行完成也会直接关闭掉不在继续执行

            //如果不设置改参数,则创建的是前台线程
            //如果这时直接关闭界面,如果该线程调用的方法没有执行完成,线程不会关闭会继续运行
            //这是因为我们关闭窗体的时候只关闭了前台主线程,而我们创建的这个前台线程没有一起关闭
            th.IsBackground = true;

            //注意这里的Start,并不是直接就启动该线程
            //而是告诉CPU,该线程已经准备好了,可以被调用了
            //但是只有CPU空闲的时候才会开始调用,如果CPU很忙,就算是启动了多线程也不会立刻调用该线程
            th.Start();
        }

        Thread thNew;
        /// <summary>
        /// 调用Test2方法,把结果输出到文本框中
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            //让主线程睡3秒再执行下面的操作
            Thread.Sleep(3000);

            thNew = new Thread(Test2);
            thNew.IsBackground = true;
            thNew.Start();
        }

        /// <summary>
        ///
        /// </summary>
        private void Test()
        {
            for (int i = 0; i < 10000; i++)
            {
                Console.WriteLine(i.ToString());
            }
        }

        /// <summary>
        ///
        /// </summary>
        private void Test2()
        {
            for (int i = 0; i < 10000; i++)
            {
                //如果直接赋值会报错
                //应为文本框是在界面加载的时候由主线程创建的
                //而调用该方法是在我们新创建的线程中操作的,这就出现了跨线程访问的问题
                //如果不要让他检测是否跨线程操作的,则需要在构造函数或者load方法中设置Control.CheckForIllegalCrossThreadCalls = false;
                textBox1.Text = i.ToString();

                //ps:如果在Test2方法没有执行完的时候直接关闭界面,则可能会报【无法访问已释放的对象】
                //这是因为文本框是主线程创建出来的,当关闭界面的时候主线程已经关闭,则其创建的文本框也会被释放而不再存在
                //而这时我们创建的新线程却还在访问主线程创建的文本框对象
                //这是后的文本框对象已经释放,所以才会因为找不到而报错
                //要处理该报错,需要在关闭主线程的时候同时关闭我们创建的线程
                //需要在Form1_FormClosing中处理
            }
        }

        /// <summary>
        /// 关闭窗体的时候关闭我们创建的后台线程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            //当我们关闭窗体的时候关闭我们创建的后台线程
            if (thNew != null)
            {
                //使用Abort来终止线程并且释放线程所占用的资源
                //而且线程一旦被关闭则不能再被起启动
                thNew.Abort();
            }
        }

        /// <summary>
        /// 带参数的线程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            Thread th = new Thread(Test3);
            th.IsBackground = true;
            th.Start("丽丽");
        }

        /// <summary>
        /// 方法的参数类型只能是object,如果定义其他类型会报错
        /// </summary>
        /// <param name="obj"></param>
        public void Test3(object obj)
        {
            string name = obj.ToString();
            MessageBox.Show("我叫" + name);
        }





猜你喜欢

转载自blog.csdn.net/m0_37532448/article/details/80321571