zoukankan      html  css  js  c++  java
  • C# 多线程之线程控制

    方案一:

       调用线程控制方法.启动:Thread.Start();停止:Thread.Abort();暂停:Thread.Suspend();继续:Thread.Resume();

     

            private void btn_Start_Click(object sender, EventArgs e)
            {
                mThread.Start();  // 开始
            }
    
            private void btn_Stop_Click(object sender, EventArgs e)
            {
                mThread.Abort();  // 终止
            }
    
            private void btn_Suspend_Click(object sender, EventArgs e)
            {
                mThread.Suspend();  // 暂停
            }
    
            private void btn_Resume_Click(object sender, EventArgs e)
            {
                mThread.Resume();  // 继续
            }

    线程定义为:

                mThread = new Thread(() =>
                {
                    try
                    {
                        for (int j = 0; j < 20; j++)
                        {
                            int vSum = 0;
                            this.textBox1.Text += "--->";
                            for (int i = 0; i < 100000000; i++)
                            {
                                if (i % 2 == 0)
                                {
                                    vSum += i;
                                }
                                else
                                {
                                    vSum -= i;
                                }
                            }
                            this.textBox1.Text += string.Format("{0} => vSum = {1}
    ", DateTime.Now.ToString(), vSum);
                            Thread.Sleep(1000);
                        }
                    }
                    catch (ThreadAbortException ex)
                    {
                        Console.WriteLine("ThreadAbortException:{0}", ex.Message);
                    }
                });

    值得注意的是: 通过 Thread.Abort() 停下来的线程(或自行运行结束的线程),都无法直接通过 Thread.Start() 方法再次启动,必须重新创建一个线程启动。

    所以,“开始按钮”事件应为:

            private void btn_Start_Click(object sender, EventArgs e)
            {
                // 定义线程
                mThread = new Thread(() => // Lambda 表达式
                {
                    try
                    {
                        for (int j = 0; j < 20; j++)
                        {
                            int vSum = 0;
                            this.textBox1.Text += "--->";
                            for (int i = 0; i < 100000000; i++)
                            {
                                if (i % 2 == 0)
                                {
                                    vSum += i;
                                }
                                else
                                {
                                    vSum -= i;
                                }
                            }
                            this.textBox1.Text += string.Format("{0} => vSum = {1}
    ", DateTime.Now.ToString(), vSum);
                            Thread.Sleep(1000);
                        }
                    }
                    catch (ThreadAbortException ex)
                    {
                        Console.WriteLine("ThreadAbortException:{0}", ex.Message);
                    }
                });
    
                mThread.Start();  // 开始
            }

    此外,对于 Thread.Suspend() 和 Thread.Resume() 方法,微软已经将其标记为过时:

    Thread.Suspend has been deprecated.  Please use other classes in System.Threading, such as Monitor, Mutex, Event, and Semaphore, to synchronize Threads or protect resources.  http://go.microsoft.com/fwlink/?linkid=14202(Thread.Suspend 已被否决。请使用系统中的其他类线程,如监视器、互斥体、事件和信号量,以同步线程或保护资源。http://go.microsoft.com/fwlink/?linkid=14202)

    因为,无法判断当前挂起线程时它正在执行什么代码。如果在安全权限评估期间挂起持有锁的线程,则 AppDoamin 中的其它线程可能被阻止。如果在线程正执行构造函数时挂起它,则 AppDomain 中尝试使用该类的其它线程将被阻止。这样容易发生死锁。

    方案二:

       在 线程运行过程中 适当的位置(如某个完整的功能/命令后)判断是否要继续线程,再决定线程的命运。

      1.定义一个全局变量:

            int mTdFlag = 0; // 1:正常运行;2:暂停;3:停止

      2. 定义一个判断方法:

            bool WaitForContinue()
            {
                if (this.mTdFlag == 3)
                {
                    return false; // 返回false,线程停止
                }
                else if (this.mTdFlag == 2)
                {
                    while (mTdFlag != 1)
                    {
                        Thread.Sleep(200); // 假暂停;停顿时间越短,越灵敏
                        if (this.mTdFlag == 3)
                        {
                            return false; // 返回false,线程停止
                        }
                    }
                }
                return true; // 返回true,线程继续
            }

        3.修改 控制命令 事件:

            private void btn_Stop_Click(object sender, EventArgs e)
            {
                this.mTdFlag = 3;
                //mThread.Abort();  // 终止
            }
    
            private void btn_Suspend_Click(object sender, EventArgs e)
            {
                this.mTdFlag = 2;
                //mThread.Suspend();  // 暂停
            }
    
            private void btn_Resume_Click(object sender, EventArgs e)
            {
                this.mTdFlag = 1;
                //mThread.Resume();  // 继续
            }

       4.在线程运行过程中适当的位置,判断线程是否继续

                mThread = new Thread(() =>
                {
                    try
                    {
                        for (int j = 0; j < 20; j++)
                        {
                            int vSum = 0;
                            this.textBox1.Text += "--->";
                            for (int i = 0; i < 100000000; i++)
                            {
                                if (i % 2 == 0)
                                {
                                    vSum += i;
                                }
                                else
                                {
                                    vSum -= i;
                                }
                                if (i % 10000000 == 0)
                                {
                                    this.textBox1.Text += ".";
                                }
                                if (!WaitForContinue()) // 返回 false 则,停止
                                {
                                    break;
                                    //return;
                                }
                            }
                            this.textBox1.Text += string.Format("{0} => vSum = {1}
    ", DateTime.Now.ToString(), vSum);
                            if (!WaitForContinue()) // 返回 false 则,停止
                            {
                                break;
                                // return;
                            }
                            Thread.Sleep(1000);
                        }
                    }
                    catch (ThreadAbortException ex)
                    {
                        Console.WriteLine("ThreadAbortException:{0}", ex.Message);
                        this.textBox1.Text += ex.Message + "...";
                    }
                    finally
                    {
                        this.textBox1.Text += "线程已结束";
                    }
                });

    在窗体中,解决跨线程访问问题:在窗体构造函数中添加代码:  Control.CheckForIllegalCrossThreadCalls = false;

    [http://www.cnblogs.com/CUIT-DX037/]

  • 相关阅读:
    使pre的内容自动换行
    textarea文本换行和页面显示换行符
    SQL查询包含汉字的行
    网站引导页插件intro.js 的用法
    jquery.cookie中的操作
    sql自动生成汉语拼音和首字母函数
    IE,Chrome滚动条样式CSS
    Vcenter server 5.5上传ISO镜像
    Vcenter server 5.5添加用户角色及分配权限
    Vcenter server 5.5安装部署
  • 原文地址:https://www.cnblogs.com/CUIT-DX037/p/6955873.html
Copyright © 2011-2022 走看看