求助,C#如何安全的关闭线程,之后在重新打开这个线程?

问题描述

程序运行时开启了一个线程,当点击一个按钮时需要开打一个窗体,此时需要关闭这个线程,当返回主界面时需要重新开启这个线程,求助怎么样才能安全的关闭和开启,我用的是thread.suspend来挂起线程,用thread.resume来重新开启现场,出现的问题是有的时候会出现死机的情况,求助怎样才能安全的实现以上功能,不会出现程序死机。

解决方案

解决方案二:

线程方法是怎样的?
解决方案三:

this.Label1.InvokeEx(e=>e.Text=DateTime.Now);试试加入界面防止死机
解决方案四:

让线程sleep呢?
解决方案五:

suspend()、resume()这个方法已经过时了,并且是不被推荐的。一个线程去强制停止另外一个正在运行的线程是有风险的。如果你需要停止的线程是一个循环机制的,可以使用标志位,需要停止的线程去检查这个标志位,如果为TRUE就休眠,直到为false才运行。这是我已知最安全的方式了。
解决方案六:

https://msdn.microsoft.com/zh-cn/library/system.threading.thread.suspend(v=vs.100).aspx
解决方案七:

我觉得对待处理线程状态的操作问题之前,首先要搞清楚线程的几种状态的概念。按照我个人对这个问题的理解,给楼主提供下面的思路,不知道可行性如何?首先,要保证线程函数正常退出,实际上当线程函数执行完毕且正常退出之后,也就意味着这个线程也将“退场”(线程正常结束)。我的想法是在你的线程函数中加一个While(新窗体.flag)状态监视的循环,这个flag就是标识你是否已经打开了一个新的窗体。如果新打开了一个窗体,你就把flag这个变量置成flase,这个时候,线程函数就会跳出while循环,朝着线程函数的“最后”方向执行,指导退出线程函数,线程函数退出,那么线程也就结束了。当再一次返回主界面的时候,再重新开启一下线程就可以。这个思路的关键是要传递flag的值,可以在实例化新窗体的时候传值。在你的新窗体定义一个全局变量publicstaticflag=true;,构造函数中flag=false;这样就可以在你的线程函数中监视窗体的状态了。
解决方案八:

引用1楼shingoscar的回复:

线程方法是怎样的?

thread.start();开启线程后用需要关闭时用thread.suspend挂起,需要开启后用thread.resume恢复线程
解决方案九:

引用2楼w6579106的回复:

this.Label1.InvokeEx(e=>e.Text=DateTime.Now);试试加入界面防止死机

这个方法具体怎么用呢,方便给个具体样例出来嘛
解决方案十:

引用7楼gold8fish的回复:

Quote: 引用1楼shingoscar的回复:
线程方法是怎样的?

thread.start();开启线程后用需要关闭时用thread.suspend挂起,需要开启后用thread.resume恢复线程

线程函数是怎样的?不是问你是怎么操作的
解决方案十一:

引用4楼u013421223的回复:

suspend()、resume()这个方法已经过时了,并且是不被推荐的。一个线程去强制停止另外一个正在运行的线程是有风险的。如果你需要停止的线程是一个循环机制的,可以使用标志位,需要停止的线程去检查这个标志位,如果为TRUE就休眠,直到为false才运行。这是我已知最安全的方式了。

嗯,好的,还有割问题,要是我用thread.abort();方法关闭此线程,需要的时候在重开打开,会有什么问题吗
解决方案十二:

引用6楼Tidal_Choidi的回复:

我觉得对待处理线程状态的操作问题之前,首先要搞清楚线程的几种状态的概念。按照我个人对这个问题的理解,给楼主提供下面的思路,不知道可行性如何?首先,要保证线程函数正常退出,实际上当线程函数执行完毕且正常退出之后,也就意味着这个线程也将“退场”(线程正常结束)。我的想法是在你的线程函数中加一个While(新窗体.flag)状态监视的循环,这个flag就是标识你是否已经打开了一个新的窗体。如果新打开了一个窗体,你就把flag这个变量置成flase,这个时候,线程函数就会跳出while循环,朝着线程函数的“最后”方向执行,指导退出线程函数,线程函数退出,那么线程也就结束了。当再一次返回主界面的时候,再重新开启一下线程就可以。这个思路的关键是要传递flag的值,可以在实例化新窗体的时候传值。在你的新窗体定义一个全局变量publicstaticflag=true;,构造函数中flag=false;这样就可以在你的线程函数中监视窗体的状态了。

嗯,好的,在请问一个问题,我要是用thread.abort();来中止这个线程,需要的时候再重新实例化线程并调用thread.start();再开始这个线程,这样会有什么问题吗?具体代码如下:privatevoidExit_Click(objectsender,EventArgse){if(Global.Power=="1"){t3.Abort();//关闭t3线程mb.Close();Formmanual=newManual();manual.ShowDialog();if(manual.DialogResult==DialogResult.OK){if(mb.Open("COM3",Convert.ToInt32("9600"),8,Parity.None,StopBits.One)){label18.Text="Manual";MessageBox.Show("COM3OpenSuccess!");Thread.Sleep(50);t3=newThread(DataShow);//重新打开t3线程t3.Start();}else{MessageBox.Show("串口打开失败,请检查线路!");}}}}
解决方案十三:

引用9楼shingoscar的回复:

Quote: 引用7楼gold8fish的回复:
Quote: 引用1楼shingoscar的回复:
线程方法是怎样的?

thread.start();开启线程后用需要关闭时用thread.suspend挂起,需要开启后用thread.resume恢复线程

线程函数是怎样的?不是问你是怎么操作的

好的,线程函数是这样的:privatevoidDataShow(){while(true){Thread.Sleep(50);short[]values=newshort[Convert.ToInt32("5")*2];intlength=Convert.ToInt32("5")*2;pollStart=Convert.ToUInt16("15");//起始寄存器地址pollLength=Convert.ToUInt16(length.ToString());。。。。。。。。。。//一些列程序代码try{while(!mb.SendFc3(Convert.ToByte("1"),pollStart,pollLength,refvalues));}catch(Exceptionerr){}}
解决方案十四:

引用10楼gold8fish的回复:

Quote: 引用4楼u013421223的回复:
suspend()、resume()这个方法已经过时了,并且是不被推荐的。一个线程去强制停止另外一个正在运行的线程是有风险的。如果你需要停止的线程是一个循环机制的,可以使用标志位,需要停止的线程去检查这个标志位,如果为TRUE就休眠,直到为false才运行。这是我已知最安全的方式了。

嗯,好的,还有割问题,要是我用thread.abort();方法关闭此线程,需要的时候在重开打开,会有什么问题吗

https://msdn.microsoft.com/zh-cn/library/5b50fdsz(v=vs.110).aspxC#比做android最好的优势就是不翻墙看官方文档,你居然不看。
解决方案十五:

引用12楼gold8fish的回复:

Quote: 引用9楼shingoscar的回复:
Quote: 引用7楼gold8fish的回复:
Quote: 引用1楼shingoscar的回复:
线程方法是怎样的?

thread.start();开启线程后用需要关闭时用thread.suspend挂起,需要开启后用thread.resume恢复线程

线程函数是怎样的?不是问你是怎么操作的

好的,线程函数是这样的:privatevoidDataShow(){while(true){Thread.Sleep(50);short[]values=newshort[Convert.ToInt32("5")*2];intlength=Convert.ToInt32("5")*2;pollStart=Convert.ToUInt16("15");//起始寄存器地址pollLength=Convert.ToUInt16(length.ToString());。。。。。。。。。。//一些列程序代码try{while(!mb.SendFc3(Convert.ToByte("1"),pollStart,pollLength,refvalues));}catch(Exceptionerr){}}

在while后面再加while(一个全局变量,窗体打开时为true,关闭时为false){Thread.Sleep(0)}
解决方案:引用11楼gold8fish的回复:

Quote: 引用6楼Tidal_Choidi的回复:
我觉得对待处理线程状态的操作问题之前,首先要搞清楚线程的几种状态的概念。按照我个人对这个问题的理解,给楼主提供下面的思路,不知道可行性如何?首先,要保证线程函数正常退出,实际上当线程函数执行完毕且正常退出之后,也就意味着这个线程也将“退场”(线程正常结束)。我的想法是在你的线程函数中加一个While(新窗体.flag)状态监视的循环,这个flag就是标识你是否已经打开了一个新的窗体。如果新打开了一个窗体,你就把flag这个变量置成flase,这个时候,线程函数就会跳出while循环,朝着线程函数的“最后”方向执行,指导退出线程函数,线程函数退出,那么线程也就结束了。当再一次返回主界面的时候,再重新开启一下线程就可以。这个思路的关键是要传递flag的值,可以在实例化新窗体的时候传值。在你的新窗体定义一个全局变量publicstaticflag=true;,构造函数中flag=false;这样就可以在你的线程函数中监视窗体的状态了。

嗯,好的,在请问一个问题,我要是用thread.abort();来中止这个线程,需要的时候再重新实例化线程并调用thread.start();再开始这个线程,这样会有什么问题吗?具体代码如下:privatevoidExit_Click(objectsender,EventArgse){if(Global.Power=="1"){t3.Abort();//关闭t3线程mb.Close();Formmanual=newManual();manual.ShowDialog();if(manual.DialogResult==DialogResult.OK){if(mb.Open("COM3",Convert.ToInt32("9600"),8,Parity.None,StopBits.One)){label18.Text="Manual";MessageBox.Show("COM3OpenSuccess!");Thread.Sleep(50);t3=newThread(DataShow);//重新打开t3线程t3.Start();}else{MessageBox.Show("串口打开失败,请检查线路!");}}}}

========================================================================================"下面我们来解释一下Abort()方法是如何工作的。因为公用语言运行时管理了所有的托管的线程,同样它能在每个线程内抛出异常。Abort()方法能在目标线程中抛出一个ThreadAbortException异常从而导致目标线程的终止。不过Abort()方法被调用后,目标线程可能并不是马上就终止了。因为只要目标线程正在调用非托管的代码而且还没有返回的话,该线程就不会立即终止。而如果目标线程在调用非托管的代码而且陷入了一个死循环的话,该目标线程就根本不会终止。不过这种情况只是一些特例,更多的情况是目标线程在调用托管的代码,一旦Abort()被调用那么该线程就立即终止了。"
解决方案:引用15楼Tidal_Choidi的回复:

Quote: 引用11楼gold8fish的回复:
Quote: 引用6楼Tidal_Choidi的回复:
我觉得对待处理线程状态的操作问题之前,首先要搞清楚线程的几种状态的概念。按照我个人对这个问题的理解,给楼主提供下面的思路,不知道可行性如何?首先,要保证线程函数正常退出,实际上当线程函数执行完毕且正常退出之后,也就意味着这个线程也将“退场”(线程正常结束)。我的想法是在你的线程函数中加一个While(新窗体.flag)状态监视的循环,这个flag就是标识你是否已经打开了一个新的窗体。如果新打开了一个窗体,你就把flag这个变量置成flase,这个时候,线程函数就会跳出while循环,朝着线程函数的“最后”方向执行,指导退出线程函数,线程函数退出,那么线程也就结束了。当再一次返回主界面的时候,再重新开启一下线程就可以。这个思路的关键是要传递flag的值,可以在实例化新窗体的时候传值。在你的新窗体定义一个全局变量publicstaticflag=true;,构造函数中flag=false;这样就可以在你的线程函数中监视窗体的状态了。

嗯,好的,在请问一个问题,我要是用thread.abort();来中止这个线程,需要的时候再重新实例化线程并调用thread.start();再开始这个线程,这样会有什么问题吗?具体代码如下:privatevoidExit_Click(objectsender,EventArgse){if(Global.Power=="1"){t3.Abort();//关闭t3线程mb.Close();Formmanual=newManual();manual.ShowDialog();if(manual.DialogResult==DialogResult.OK){if(mb.Open("COM3",Convert.ToInt32("9600"),8,Parity.None,StopBits.One)){label18.Text="Manual";MessageBox.Show("COM3OpenSuccess!");Thread.Sleep(50);t3=newThread(DataShow);//重新打开t3线程t3.Start();}else{MessageBox.Show("串口打开失败,请检查线路!");}}}}

========================================================================================"下面我们来解释一下Abort()方法是如何工作的。因为公用语言运行时管理了所有的托管的线程,同样它能在每个线程内抛出异常。Abort()方法能在目标线程中抛出一个ThreadAbortException异常从而导致目标线程的终止。不过Abort()方法被调用后,目标线程可能并不是马上就终止了。因为只要目标线程正在调用非托管的代码而且还没有返回的话,该线程就不会立即终止。而如果目标线程在调用非托管的代码而且陷入了一个死循环的话,该目标线程就根本不会终止。不过这种情况只是一些特例,更多的情况是目标线程在调用托管的代码,一旦Abort()被调用那么该线程就立即终止了。"

好的,也就是说,如果我的线程函数中不存在死循环,这个方法是可以正常使用的,我的线程函数是用来串口通讯的,实时读取串口数据,要是串口通讯出现卡死,就是陷入死循环的话,以上方法的线程事中止不了的,再次开启这个线程会出现问题。
解决方案:4楼、6楼都讲的比较到位了线程要安全关闭,只能靠自行退出,否则就会有资源泄露或者崩溃的风险
解决方案:引用14楼u013421223的回复:

Quote: 引用12楼gold8fish的回复:
Quote: 引用9楼shingoscar的回复:
Quote: 引用7楼gold8fish的回复:
Quote: 引用1楼shingoscar的回复:
线程方法是怎样的?

thread.start();开启线程后用需要关闭时用thread.suspend挂起,需要开启后用thread.resume恢复线程

线程函数是怎样的?不是问你是怎么操作的

好的,线程函数是这样的:privatevoidDataShow(){while(true){Thread.Sleep(50);short[]values=newshort[Convert.ToInt32("5")*2];intlength=Convert.ToInt32("5")*2;pollStart=Convert.ToUInt16("15");//起始寄存器地址pollLength=Convert.ToUInt16(length.ToString());。。。。。。。。。。//一些列程序代码try{while(!mb.SendFc3(Convert.ToByte("1"),pollStart,pollLength,refvalues));}catch(Exceptionerr){}}

在while后面再加while(一个全局变量,窗体打开时为true,关闭时为false){Thread.Sleep(0)}

引用14楼u013421223的回复:

Quote: 引用12楼gold8fish的回复:
Quote: 引用9楼shingoscar的回复:
Quote: 引用7楼gold8fish的回复:
Quote: 引用1楼shingoscar的回复:
线程方法是怎样的?

thread.start();开启线程后用需要关闭时用thread.suspend挂起,需要开启后用thread.resume恢复线程

线程函数是怎样的?不是问你是怎么操作的

好的,线程函数是这样的:privatevoidDataShow(){while(true){Thread.Sleep(50);short[]values=newshort[Convert.ToInt32("5")*2];intlength=Convert.ToInt32("5")*2;pollStart=Convert.ToUInt16("15");//起始寄存器地址pollLength=Convert.ToUInt16(length.ToString());。。。。。。。。。。//一些列程序代码try{while(!mb.SendFc3(Convert.ToByte("1"),pollStart,pollLength,refvalues));}catch(Exceptionerr){}}

在while后面再加while(一个全局变量,窗体打开时为true,关闭时为false){Thread.Sleep(0)}

如果需要再次开启线程,只需要将这个全局变量值置位true嘛?
解决方案:引用6楼Tidal_Choidi的回复:

我觉得对待处理线程状态的操作问题之前,首先要搞清楚线程的几种状态的概念。按照我个人对这个问题的理解,给楼主提供下面的思路,不知道可行性如何?首先,要保证线程函数正常退出,实际上当线程函数执行完毕且正常退出之后,也就意味着这个线程也将“退场”(线程正常结束)。我的想法是在你的线程函数中加一个While(新窗体.flag)状态监视的循环,这个flag就是标识你是否已经打开了一个新的窗体。如果新打开了一个窗体,你就把flag这个变量置成flase,这个时候,线程函数就会跳出while循环,朝着线程函数的“最后”方向执行,指导退出线程函数,线程函数退出,那么线程也就结束了。当再一次返回主界面的时候,再重新开启一下线程就可以。这个思路的关键是要传递flag的值,可以在实例化新窗体的时候传值。在你的新窗体定义一个全局变量publicstaticflag=true;,构造函数中flag=false;这样就可以在你的线程函数中监视窗体的状态了。

用了您说的方法,安全关闭这个线程后,我再次开启这个线程是把flag设为true,将thread.start();是这个步骤嘛?
解决方案:引用6楼Tidal_Choidi的回复:

我觉得对待处理线程状态的操作问题之前,首先要搞清楚线程的几种状态的概念。按照我个人对这个问题的理解,给楼主提供下面的思路,不知道可行性如何?首先,要保证线程函数正常退出,实际上当线程函数执行完毕且正常退出之后,也就意味着这个线程也将“退场”(线程正常结束)。我的想法是在你的线程函数中加一个While(新窗体.flag)状态监视的循环,这个flag就是标识你是否已经打开了一个新的窗体。如果新打开了一个窗体,你就把flag这个变量置成flase,这个时候,线程函数就会跳出while循环,朝着线程函数的“最后”方向执行,指导退出线程函数,线程函数退出,那么线程也就结束了。当再一次返回主界面的时候,再重新开启一下线程就可以。这个思路的关键是要传递flag的值,可以在实例化新窗体的时候传值。在你的新窗体定义一个全局变量publicstaticflag=true;,构造函数中flag=false;这样就可以在你的线程函数中监视窗体的状态了。

用这种方法试了一下,发现重新开启线程后,线程有的时候会开启失败,我的指导退出步骤为:在线程函的while为false后,用return结束函数,然后需要重新开启线程时用thread.start开启
解决方案:引用20楼gold8fish的回复:

Quote: 引用6楼Tidal_Choidi的回复:
我觉得对待处理线程状态的操作问题之前,首先要搞清楚线程的几种状态的概念。按照我个人对这个问题的理解,给楼主提供下面的思路,不知道可行性如何?首先,要保证线程函数正常退出,实际上当线程函数执行完毕且正常退出之后,也就意味着这个线程也将“退场”(线程正常结束)。我的想法是在你的线程函数中加一个While(新窗体.flag)状态监视的循环,这个flag就是标识你是否已经打开了一个新的窗体。如果新打开了一个窗体,你就把flag这个变量置成flase,这个时候,线程函数就会跳出while循环,朝着线程函数的“最后”方向执行,指导退出线程函数,线程函数退出,那么线程也就结束了。当再一次返回主界面的时候,再重新开启一下线程就可以。这个思路的关键是要传递flag的值,可以在实例化新窗体的时候传值。在你的新窗体定义一个全局变量publicstaticflag=true;,构造函数中flag=false;这样就可以在你的线程函数中监视窗体的状态了。

用这种方法试了一下,发现重新开启线程后,线程有的时候会开启失败,我的指导退出步骤为:在线程函的while为false后,用return结束函数,然后需要重新开启线程时用thread.start开启

====================================================================================怎么个开启失败呢?你确定是线程开启失败?可以在你要执行的线程函数中加入断点,判断一下每次开启线程的时候是否能执行到断点处。提醒你一下:有时候你开启线程并不是线程函数就会按照咱们想象的那样瞬间就执行了,因为线程的调度和优先级的原因,会有延迟的,但只是执行的时间早晚的问题,理论上是一定能够执行到线程函数的断点处的。

时间: 2024-09-19 14:02:24

求助,C#如何安全的关闭线程,之后在重新打开这个线程?的相关文章

java 线程池中如何自定义每个线程名称

问题描述 java 线程池中如何自定义每个线程名称 **java 线程池中如何自定义每个线程名称 java 线程池中如何自定义每个线程名称 ** 解决方案 补充下,线程池的创建线程池对象时,有一个参数是ThreadFactory类型,如果不传递,默认用的是DefaultFactory,我们可以自定义一个ThreadFactory然后作为参数传到进去,这个类里面就可以自定义线程池中创建的线程的名称.api: public ThreadPoolExecutor(int corePoolSize,in

线程管理(四)操作线程的中断机制

操作线程的中断机制 在之前的指南里,你学习了如何中断执行线程和如何对Thread对象的中断控制.之前例子中的机制可以很容易中断的线程中使用.但是如果线程实现的是由复杂的算法分成的一些方法,或者它的方法有递归调用,那么我们可以用更好的机制来控制线程中断.为了这个Java提供了InterruptedException异常.当你检测到程序的中断并在run()方法内捕获,你可以抛这个异常. 在这个指南中, 我们将实现的线程会根据给定的名称在文件件和子文件夹里查找文件,这个将展示如何使用Interrupt

java线程编程(一):线程基础

在学习java中,我发现有关于对线程的讲解比较少,我打算为一些java初学者提一些关于线程方面的参考, 为深入学习java奠定基础.我本着共同进步的原则特写下了关于java线程编程的一系列文章 java线程编程(一):线程基础 ◆线程(thread)其实是控制线程(thread of control)的缩写. 每一个线程都是独立的,因此线程中的每个方法的局部变量都是和其他线程隔离开的,这些变量完全是私有的,因此对于 线程而言,是没有办法访问其他线程的局部变量的.如果两个线程同时访问同一个方法,则

Win8系统关闭飞行模式后无法打开wifi怎么办?

  Win8系统关闭飞行模式后无法打开wifi怎么办?          1.进入[控制面板]->[网络与共享中心],点击"问题疑难解答"; 2.选择"网络适配器".在弹出来的窗口点击下一步进行问题检测; 3.然后选择"网络适配器"界面中的"wifi"选项,点击下一步查询到问题原因; 4.选择应用此修复,即完成wifi的重新启动. windows7教程 windows8教程 windows10教程

求教我用dsoframer.ocx将excel文档内嵌在winform中,如何将这个子界面关闭,方便下次重新打开

问题描述 c#求教我用dsoframer.ocx将excel文档内嵌在winform的子界面中,如何将这个子界面正确的关闭,方便下次重新打开,axFramerControl.Open(System.IO.Directory.GetCurrentDirectory()+"\excel1.XLS");我用的是这个打开语句,请问我要将这个子界面关闭该如何关闭,方便再次打开.谢谢! 解决方案 解决方案二:放到一个单独窗体里打开,关闭窗体也就关了

深入Java线程管理(一):线程的实现方式

Java的线程实现方式一共有三种,继承Thread.实现Runable接口,实现Callable接口.不过实现Runnable接口与实现Callable接口的方式基本相同,只是Callable接口里定义的方法有返回值,可以声明抛出异常而已. 一. 继承Thread类创建线程类 1) 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务. 2) 创建Thread子类的实例,即创建了线程对象. 3) 调用线程对象的start()方法来启动该线程.

多线程-JAVA中如何在一个线程里面停掉另一个线程

问题描述 JAVA中如何在一个线程里面停掉另一个线程 JAVA中如何在一个线程里面停掉另一个线程,是在一个线程里面哦 PS:新人第一次问问题,希望大神求教 解决方案 定义一个共享变量在run方法里面 while(start){ } 解决方案二: 所以说,这个问题的答案是:不可以! 虽然的确有那么个方法可以摧毁别人的线程,但很早很早就已经过期了,如果没记错的话我之前也这么玩,而结果是这个过期的方法根本没有作用-- 虽然说办法不是没有,那就是通过改变变量值,它知道自己该死了,就退出循环,走向结束.

java线程-java中的多线程?线程的并发问题

问题描述 java中的多线程?线程的并发问题 多线程具体代表java中程序的什么?它指的实际功能上的什么情况?详细求解 解决方案 多线程和进程的关系详解: 1.当我们运行QQ程序时,操作系统就会为这个程序创建一个QQ进程(QQ~PCB)并且分配CPU.内存等资源. 2.但这个进程中包含着:发送大型的线程.接受文件的线程.发送文字信息的线程.发送文字信息的线程等多个不同功能的线程. 因而我们才能一边发送文件,一边发送文字信息同时操作.这些线程都共享着QQ进程中的CPU.内存等资源. 总结:所以说进

深入Java线程管理(三):线程同步

一. 引入同步: 有一个很经典的案例,即银行取款问题.我们可以先看下银行取款的基本流程: 1)用户输入账户.密码,系统判断用户的账户.密码是否匹配. 2)用户输入取款金额. 3)系统判断账户金额是否大于取款金额. 4)如果余额大于取款金额,则取款成功:如果余额小于取款金额,则取款失败. 假设,此时有两个人,同时使用同一个账户并发取钱,我们模拟下取款流程: public class Account { // 封装账户编号.账户余额两个Field private String accountNo;