问题描述
现在有个界面,我点击一个按钮,启动后台线程_backgroundWorker,在_backgroundWorker_DoWork里面我调用一个其他类的方法A(),在A里面有个循环查找,时间很长,现在问题就是我在后台线程开启之后,中途关闭这个窗体,在关闭事件里面这么写的if(_backgroundWorker.IsBusy){_backgroundWorker.CancelAsync();//取消掉Completed事件,不进行接收_backgroundWorker.RunWorkerCompleted-=newRunWorkerCompletedEventHandler(_backgroundWorker_RunWorkerCompleted);}原因是不知道怎么结束掉这个进程,只能在接收上做处理了,因为处理结果和提示都在Completed里面,这样做也可以达到我要的效果,但是后台线程没有结束,有点小担忧,所有求个方法结束掉这个后台进程。在网上找了下,都是只能在_backgroundWorker_DoWork这个事件里面循环才能用e.Cancel结束,我能想到的就是用一个全局变量控制,窗体关闭时给全局变量赋值,然后在循环里面判断,有别的方法么
解决方案
解决方案二:
_backgroundWorker.CancelAsync();只是一个状态判断,不会终止线程的你在A()方法里面要做if(e.Cancel){return;}跳出这个方法才会让线程停掉线程只有这方法停止其他的
解决方案三:
引用1楼wyd1520的回复:
_backgroundWorker.CancelAsync();只是一个状态判断,不会终止线程的你在A()方法里面要做if(e.Cancel){return;}跳出这个方法才会让线程停掉线程只有这方法停止其他的
我知道要在DoWork里面判断e.Cancel可是循环在其他类里面,根本就取不到这个e,void_backgroundWorker_DoWork(objectsender,DoWorkEventArgse){A();}已经进入到A方法了,在A里面循环,我要做的就是在循环里面做是否中断的判断,但是这个e.Cancel在A里面取不到
解决方案四:
最优雅的方案当然是实现协作取消(主动判断状态,停止循环),然而就像LZ的状况,执行自己不能控制的长时间任务的话,想取消那就只能自己创建并控制线程,需要的时候Abort了。不过这种暴力手段有一定危险性,需要执行的代码中能够适应突然冒出来的ThreadAbortException,可能导致状态损坏和资源泄露。一般如果是自己的代码,最好还是想办法实现协作取消(让执行的任务接受一个取消标识来进行判断)。如果是第三方代码,稳妥一点的方式是使用应用程序域隔离,这个可以通过卸载/重建AppDomain来防止托管状态损坏的可能,然而还是有可能产生非托管资源泄露。最终手段是进程隔离。
解决方案五:
用个全局bool变量判断吧.
解决方案六:
引用2楼powerat123的回复:
我知道要在DoWork里面判断e.Cancel可是循环在其他类里面,根本就取不到这个e,void_backgroundWorker_DoWork(objectsender,DoWorkEventArgse){A();}已经进入到A方法了,在A里面循环,我要做的就是在循环里面做是否中断的判断,但是这个e.Cancel在A里面取不到
当参数传进去啊
解决方案七:
引用5楼shingoscar的回复:
Quote: 引用2楼powerat123的回复:
我知道要在DoWork里面判断e.Cancel可是循环在其他类里面,根本就取不到这个e,void_backgroundWorker_DoWork(objectsender,DoWorkEventArgse){A();}已经进入到A方法了,在A里面循环,我要做的就是在循环里面做是否中断的判断,但是这个e.Cancel在A里面取不到当参数传进去啊
我试了,因为A()方法只会调用一次,即使当参数把e传过去,那也只是当时的初始值,当界面关闭后,这个e.Cancel改变后,不会影响到已经运行中的A方法,看来只能用全局参数来控制了,强制结束线程么。这是要报错的节奏。。。
解决方案八:
你可以在函数A里判断backgroundWorker1.CancellationPending这本身就已经算是个全局变量了,跟e无关的只要你执行了CancelAsync(),它就会变成true
解决方案九:
A(DoWorkEventArgse)