问题描述
各位大鸟,有个线程问题困扰我好久啦,请大鸟指导,感谢!有个相机类,里面声明啦一个类,一个委托,一个信号。然后实例化啦2个相机,对应的线程也是2个,对应的2个委托同时指向啦个方法msg(),想让2个相机的Grab()方法都执行完后,在循环下一轮。现在的问题是,只执行啦一轮,就卡在哪里啦!,并且执行啦3次,看图片,感觉AutoResetEvent.WaitAll(revents);没有用!///这是一个相机累publicclassCamera{privateThreadcamthread;//创建一个类publicAutoResetEventaevent=newAutoResetEvent(false);//创建个信号publicAction<Camera>Amsg;//创建一个委托,用于结果输出publicstringresult="";publicstringName{get;set;}publicCamera(stringName){this.Name=Name;camthread=newThread(Grab);camthread.Name=this.Name;}publicvoidRun(){camthread.Start();}publicvoidstop(){camthread.Abort();}publicvoidGrab(){intcount=0;while(true){count++;if(count%5==0){result="OK";Thread.Sleep(50);}else{result="NG";Thread.Sleep(50);}aevent.Set();//执行到这里信号打开Amsg(this);//委托值传出}}}}//调用publicpartialclassForm1:Form{publicForm1(){InitializeComponent();}staticintcamcount=2;//定义相机个数Camera[]cam=newCamera[camcount];//定义相机数组AutoResetEvent[]revents=newAutoResetEvent[camcount];//定义信号数组privatevoidForm1_Load(objectsender,EventArgse){for(inti=0;i<cam.Length;i++){cam[i]=newCamera("CAM"+i);//相机实例化revents[i]=newAutoResetEvent(false);//信号实例化为关revents[i]=cam[i].aevent;//信号对应赋值cam[i].Amsg+=msg;//委托指向msg}}///<summary>///运行所有相机///</summary>///<paramname="sender"></param>///<paramname="e"></param>privatevoidbutton1_Click(objectsender,EventArgse){for(inti=0;i<cam.Length;i++){cam[i].Run();}}intiii=0;voidmsg(CameraT)//____________________委托指向{iii++;Invoke(newAction(()=>{richTextBox1.AppendText(T.Name+"="+T.result+"nr");}));AutoResetEvent.WaitAll(revents);//等待信号都有的时候,进行下一轮工作//<<<<<<<<<<<---问题点在这里,为什么二个线程只跑了一次就停止了???????????????stringaa=iii.ToString();}privatevoidbutton2_Click(objectsender,EventArgse){for(inti=0;i<cam.Length;i++){cam[i].stop();}}}}
解决方案
解决方案二:
卡在哪里?你不会进入调试吗?或者直接暂停运行看一看?
解决方案三:
你的事件都是AutoResetEvent。因此,当多个Camera调用msg,并间接调用WaitAll的时候:cam0调用AutoResetEvent.WaitAll(revents)cam1调用AutoResetEvent.WaitAll(revents)cam2调用AutoResetEvent.WaitAll(revents)3个WaitAll只能有一个成功,因为WaitAll把AutoResetEvent的信号量重置了(AutoReset)。其他WaitAll不成功的Camera就此阻塞,再也没有机会进行下一次aevent.Set()。
解决方案四:
每个线程执行一次AutoResetEvent.WaitAll(revents);
这里是不妥当的这行代码可以防止运行相机的for循环之外
解决方案五:
http://blog.csdn.net/qq_17486399/article/details/51210053祝你理解多线程
解决方案六:
跟帖mark一下,学习
解决方案七:
usingSystem;usingSystem.Collections.Generic;usingSystem.ComponentModel;usingSystem.Data;usingSystem.Drawing;usingSystem.Linq;usingSystem.Text;usingSystem.Windows.Forms;usingSystem.Threading;namespaceTest_AutoEvent{publicpartialclassForm1:Form{publicForm1(){InitializeComponent();}staticintcamcount=2;//定义相机个数Camera[]cam=newCamera[camcount];//定义相机数组ManualResetEvent[]revents=newManualResetEvent[camcount];//定义信号数组privatevoidForm1_Load(objectsender,EventArgse){for(inti=0;i<cam.Length;i++){cam[i]=newCamera("CAM"+i);//相机实例化revents[i]=newManualResetEvent(false);//信号实例化为关revents[i]=cam[i].aevent;//信号对应赋值cam[i].Amsg+=msg;//委托指向msg}}///<summary>///运行所有相机///</summary>///<paramname="sender"></param>///<paramname="e"></param>privatevoidbutton1_Click(objectsender,EventArgse){for(inti=0;i<cam.Length;i++){cam[i].Run();//注0,这里有多个cam在一起跑。由于cam[0]比cam[1]先执行,所以输出结果总是cam[0]在cam[1]的前面。}}privateintiii=0;voidmsg(CameraT)//____________________委托指向{iii++;Invoke(newAction(()=>{richTextBox1.AppendText(T.Name+"="+T.result+"nr");}));ManualResetEvent.WaitAll(revents);//等待信号都有的时候,进行下一轮工作//由于cam[i].Run();这里的有多个cam在同时跑,他们执行aevent.Set();是不同时的,等到所有cam都执行了aevent.Set();以后,//这句:ManualResetEvent.WaitAll(revents);才会结束等待,//具体解释,请参见注0-注3。}privatevoidbutton2_Click(objectsender,EventArgse){for(inti=0;i<cam.Length;i++){cam[i].stop();}}}publicclassCamera{privateThreadcamthread;publicManualResetEventaevent=newManualResetEvent(false);publicAction<Camera>Amsg;publicstringresult="";publicstringName{get;set;}publicCamera(stringName){this.Name=Name;camthread=newThread(Grab);camthread.Name=this.Name;}publicvoidRun(){camthread.Start();}publicvoidstop(){camthread.Abort();}publicvoidGrab(){intcount=0;while(true){count++;if(count%5==0){result="OK";Thread.Sleep(50);}else{result="NG";Thread.Sleep(50);}aevent.Set();//注1,由于cam[i].Run();这里的有多个cam在同时跑,他们执行aevent.Set();是不同时的,Amsg(this);//注2,上面虽然执行了set(),但是在这个委托对应的方法里面会停止在:这句:ManualResetEvent.WaitAll(revents);等到所有cam都执行了aevent.Set();以后,才会结束等待。aevent.Reset();//注3,上面执行了waitall,这里要reset(),这句也可以放在aevent.Set();之前。}}}}
其实也可以考虑使用.net4.0的并行计算,用task.waitall,比用这个锁来同步要简单明了得多。
解决方案八:
usingSystem;usingSystem.Collections.Generic;usingSystem.ComponentModel;usingSystem.Data;usingSystem.Drawing;usingSystem.Linq;usingSystem.Text;usingSystem.Windows.Forms;usingSystem.Threading;usingSystem.Collections.Concurrent;usingSystem.Threading.Tasks;namespaceTest_AutoEvent{publicpartialclassForm1:Form{staticintcamcount=5;//定义相机个数Camera[]cam=newCamera[camcount];//定义相机数组privateboolEnableRun=true;Thread_thd=null;publicForm1(){InitializeComponent();}privatevoidForm1_Load(objectsender,EventArgse){for(inti=0;i<cam.Length;i++){cam[i]=newCamera("CAM"+i);//相机实例化cam[i]._Act+=DoAction;}_thd=newThread(RunThread);_thd.IsBackground=true;}///<summary>///运行所有相机///</summary>///<paramname="sender"></param>///<paramname="e"></param>privatevoidbutton1_Click(objectsender,EventArgse){if((_thd.ThreadState&ThreadState.Suspended)!=0){EnableRun=true;_thd.Resume();}else{_thd.Start();}}privatevoidRunThread()//task要放到后台线程里面,否则会出现界面假死,程序无法响应。{while(EnableRun){//tsk01=newTask(cam[0].Grab);//tsk02=newTask(cam[1].Grab);//tsk01=newTask(()=>cam[0].Grab());//tsk02=newTask(()=>cam[1].Grab());或者这样,这两种写法都是一样的。//tsk01.Start();//tsk02.Start();//tsk01=Task.Factory.StartNew(cam[0].Grab);//tsk02=Task.Factory.StartNew(cam[1].Grab);这样写也是可以的。Task[]_tsk=newTask[camcount];for(inti=0;i<camcount;i++){_tsk[i]=newTask(cam[i].Grab);_tsk[i].Start();}Task.WaitAll(_tsk);for(inti=0;i<camcount;i++){_tsk[i].Dispose();_tsk[i]=null;}}}privatevoidbutton2_Click(objectsender,EventArgse){EnableRun=false;_thd.Suspend();}privatevoidDoAction(Camera_cam){this.Invoke(newAction(()=>{richTextBox1.AppendText(_cam.Name+"="+_cam.result+"rn");}));}}publicclassCamera{publicstringresult="";publicstringName{get;set;}publicAction<Camera>_Act;publicCamera(stringName){this.Name=Name;}privateintcount=0;publicvoidGrab(){count++;if(count%5==0){result="OK";Thread.Sleep(50);}else{result="NG";Thread.Sleep(50);}_Act(this);}}}
以上是用task的例子,供你参考。之所以没有按照严格的cam0-cam4来执行,可能是task内部的调度机制决定的。
解决方案九:
..建议你用异步委托去做....线程这里的执行顺序有时候很乱..