在另一个窗体中建立了一个线程CircleThread,这个线程创建后休眠,需要resume后才能执行。然后,
 if not Assigned(CircleThread) then
       CircleThread := TCircleThread.Create(2, 2, 2, '2', '2');      这种情况能OK
  else begin
       CircleThread.X := 1;                               这种情况不能执行
       CircleThread.Y := 1;
       CircleThread.radius := 1;
       CircleThread.color := '1';
       CircleThread.ADeviceNo := '1';
  end;
       CircleThread.Resume;现在,没有线程创建线程后执行时是正确的;
      但是线程已存在时,线程都不执行;
是哪里有问题,不是写了CircleThread.Resume用来唤醒线程了吗?

解决方案 »

  1.   

    废话,线程不是一组函数,它是一串操作的过程,一旦线程函数退出了,线程也就结束了。线程已经存在,那是线程对象,不一定线程还存在!你好好看看Delphi关于线程的说明。特别是Execute如何设计!线程挂起后才能Resume,但是,线程退出后就不能Resume
      

  2.   

    你的线程的FreeOnTerminated是不是设置为True了啊
    就是说你的线程第一次执行完就退出了
    再Resume当然没有效果了
      

  3.   

    这个FreeOnTerminated是设置为True了,那我线程对象存在时,怎么才能让线程再次运行?
      

  4.   

    GetExitCodeThread(ThreadHandle,ExitCode)
    来取得ExitCode,如果ExitCode=STILL_ACTIVE
    表示线程还存在,对于存在的线程,则可以使用ResumeThread(ThreadHandle)来唤醒线程,如果线程仍然处于运行状态,则会返回错误具体的自己去看相关的API的返回值。
      

  5.   

    如果处于STILL_ACTIVE状态,则使用ResumeThread(线程句柄),即可,但是注意的是需要相当的权限。如果不是,则只能进行CloseHandle,再CreateThread.
      

  6.   

    if not Assigned(AlarmCircleThread) then
        begin
           AlarmCircleThread := TAlarmCircleThread.Create(2, 2, 2, '2', '2');
           AlarmCircleThread.Resume;
        end
      else begin
         IsLay :=GetExitCodeThread(AlarmCircleThread.Handle,ExitCode);
         if IsLay then begin
           if ExitCode=STILL_ACTIVE then begin
             ResumeThread(AlarmCircleThread.Handle);
             showmessage('线程在活动中')
           end
           else
             showmessage('线程已终止terminate,但句柄未释放free');
         end
         else begin
           CloseHandle(AlarmCircleThread.Handle);
           showmessage('句柄已释放');     end;
         ShowMessage('线程对象还存在');
      end;
    我是这样写的,但是还不能达到效果:(
      

  7.   

    首先要明确,当线程处于Sleep(Suspended)状态下时,你需要唤醒(Resume),但是此时可能存在三种情况:
    一、该线程对象不存在(Not Assigned),那么就需要明确是否需要再创建该线程对象,如果不需要,可能得抛出异常,给操作员或者主操作函数/过程一个异常(Exception);
    二、该线程对象存在但是线程执行体已经结束执行,此时就需要进行CloseHandle(实际上使用TThread,应该是调用Free方法),之后同情况一一致处理;
    三、该线程确实处于睡眠(Sleep,Suspended)状态,则直接调用ResumeThread(对于使用TThread类,包括子类对象应当调用其自身的Resume方法),通常Resume也并不一定会成功,则对于使用ResumeThread,则可以根据返回值进行处理,但是对于使用TThread.Resume,则另做处理,通常情况下都会认为它是成功的,这里得看个人的严谨态度,同时也视程序的可靠性要求而来,可靠性要求越高,则更需要注意各种异常的判断,特别是任何一个有返回值的函数调用都需要对返回值进行判断并加以处理,这也是一个习惯问题。对于没有返回值的过程调用通常会认为是必定成功的,但是也要视情况而定,必要时尽可能通过其它途径进行异常检验,以避免不必要的问题发生,并且通常在这种过程的调用出现问题是最能进行debug的。if not Assigned(AlarmCircleThread) then
        begin
           AlarmCircleThread := TAlarmCircleThread.Create(2, 2, 2, '2', '2');
           AlarmCircleThread.Resume;//这里使用了Resume说明TAlarmCircleThread创建时是处于睡眠状态的
        end
      else begin//线程对象仍然存在
         IsLay :=GetExitCodeThread(AlarmCircleThread.Handle,ExitCode);
         if IsLay then begin
           if ExitCode=STILL_ACTIVE then begin
             ResumeThread(AlarmCircleThread.Handle);//这里该使用AlarmCircleThread.Resume;
             showmessage('线程在活动中')
           end
           else
             showmessage('线程已终止terminate,但句柄未释放free');//这里由于线程的执行过程已经结束,华伦再世也无法让它起死回生,所以就该让它安静地去
             //Begin=====================Modify
             AlarmCircleThread.Free;
             AlarmCircleThread := TAlarmCircleThread.Create(2, 2, 2, '2', '2');
             AlarmCircleThread.Resume;
             //End=======================Modify
         end
         else begin
           //CloseHandle(AlarmCircleThread.Handle);//这里面不该是关闭句柄,这里是由于调用GetExitCodeThread失败而引发的,所以应当使用GetLastError来判断所产生的错误
           //showmessage('句柄已释放');
           //Begin=====================Modify
           raise Exception.CreateFmt('Error occured when call GetExitCodeThread! ThreadID:%d,Error Code:%d',[AlarmCircleThread.ThreadID,GetLastError]);
           //End=======================Modify            end;
         //ShowMessage('线程对象还存在');
      end;
      

  8.   

    既然是使用TThread做为基类,在线程多不便管理的情况下可以考虑使用FreeOnTerminate属性,让线程运行完毕就自行释放,当然使用这种方式,你必须得保证在线程执行体当中不出现重大的异常,而使得线程调用代码,能对线程进行管控.