日期:2014-05-17  浏览次数:20847 次

(急)结束一个线程再重新new初始化该线程,新线程跑起来很慢,阻滞(线程里有Lock块)?
这是一个和硬件打交道的线程,通过USB转CAN总线连接电机,通过调用电机厂商提供的API控制电机,因为还需要实时得到电机的信息,所以还开了个线程,为了防止同时访问总线,造成总线冲突,所以加了Lock同步块,具体是通过操作杆去控制,连接操作杆的是一个USB转232的串口,因为串口会重新插拔或松脱之类,所以做了个按钮,相当于重新初始化:过程就是1.彻底停止操作杆控制线程,2.关闭操作杆串口,3.关闭电机连接,4.重新打开操作杆串口,5.重新打开电机连接,6.初始化操作杆控制线程。
彻底停止操作杆线程的语句:

  if (threadJoyStickMaxon != null && threadJoyStickMaxon.IsAlive)
  {
                joyStickLeftPortKeepReading = false;
                threadJoyStickMaxon.Join();
                threadJoyStickMaxon = null;
  }

线程变量定义的是成员变量。
关键就在于这句 threadJoyStickMaxon = null;
如果不写这句,再初始化新的线程之前,线程的IsAlive属性为false,ThreadState为Stopped,同时界面就会很卡。如果写这句,再初始化新的线程之前,线程的IsAlive属性却为true,ThreadState却为Start,同时界面就不卡了。使线程赋为null,加速了GC对其的释放,但是在没有初始化前为什么它的IsAlive属性却为true,ThreadState却为Start呢。
更关键的使用后一种,会出现调用电机的API出现严重的错误:“不能向非托管代码传递无效的函数指针之类的。”原先初始化电机连接放在一个线程中,关闭电机连接直接放在UI线程中就会出现VC++ RuntimeLibrary Error之类的内存错误,所以后来处理的方式是在初始化线程中连接完电机后就让它WaitOne,最后关闭软件的时候通过手工重置事件再唤醒它,执行后续的关闭电机连接的操作,这样就不会在关闭软件时报这样的错误。
初始化电机线程:

 void CreateManageThreadDeviceInit()
 {
         threadDeviceInit = new Thread(ManageThreadDeviceInit);
         threadDeviceInit.Start();
 }
 void ManageThreadDeviceInit()  
 {
      OpenJoystickerLeftport();
      InitMaxon();
      joyStickLeftPortKeepReading = true;
      CreateManageThreadJoystickMaxon();   
 
       CreateManageThreadReadMaxonStatus();  //打开读电机状态线程

     deviceInitThreadResetEvent.WaitOne();   //**MJ:让初始化硬件线程阻塞,直到关闭软件的时候在唤醒它,关闭Maxon电机连接

                try  //关闭电机连接,电机API提供的方式
                {
                    maxonErrorPromptMessage = "CloseDevice";  //**MJ:如果没有成功打开Maxon电机,关闭Maxon电机连接时或者不关,都会有VC++ RunTime Library Error,定时器初始化设备有时也会,线程初始化设备是每次都有
                    if (EposCmd.Net.VcsWrapper.Device.VcsCloseDevice(keyHandle, ref errorCode) == 0)