随笔 - 52  文章 - 0  评论 - 13  阅读 - 16万

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}\r\n", 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}\r\n", 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}\r\n", 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/]

posted on   云梦鸿  阅读(3882)  评论(5编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示