unit GDKWithThread;interface
uses  Classes,Windows;type
////////////////////////////////////////////////////////////////////////////////
//以下定义线程类,这也是所有线程的基类;
TGDKThread = class
private
m_Handle       : THandle; //线程句柄
    m_ThreadID     : Cardinal;    //这个是自动获得的;
m_ID           : Integer;
m_GroupID      : Integer; //线程组别;
m_NickName    : String; //线程名称; m_IsSuspended  : Boolean;   //目前线程的状态是否挂起;
m_IsOutOfRun   : Boolean;   //是否退出了主循环
    m_IsStopped    : Boolean;
  public
    constructor Create(CreateSuspended: Boolean);  overload;
    destructor  Destroy; override;
  published
    property    Handle             : THandle      read m_Handle;
    property    ThreadID           : Cardinal     read m_ThreadID;    property    IsSuspended        : Boolean      read m_IsSuspended ;
    property    IsOutOfRun         : Boolean      read m_IsOutOfRun ;    property    ID                 : Integer      read m_ID                 write m_ID;
    property    GroupID            : Integer      read m_GroupID            write m_GroupID;
    property    NickName           : String       read m_NickName           write m_NickName;  public
procedure   MainRun; procedure   Resume;     //启动线程;
procedure   Suspend;    //挂起线程; procedure Stop;          //强制退出,其实设置  m_IsStopped = true ,等退出Run;
    function    WaitFor(ATimeout:Cardinal):Integer;   //根据一定时间,等待outofrun信号,嘿嘿; //所有的线程都必须重载此方法!!!
procedure  RunBefore;virtual; //行动准备
procedure   RunAfter ;virtual; //撤离准备
procedure  Run      ;virtual; //执行体
  end;
////////////////////////////////////////////////////////////////////////////////
implementation////////////////////////////////////////////////////////////////////////////////
function GDKThread_Entry(lpThread: Pointer): Integer;
var
  _thread : TGDKThread;
begin
  _thread := lpThread;
try
_thread.MainRun;
except
  end;
Result := 0;
end;
////////////////////////////////////////////////////////////////////////////////
{ TGDKThread }constructor TGDKThread.Create(CreateSuspended: Boolean);
var
  dwCreateFlags : DWORD;
begin
m_IsOutOfRun    := false;
  m_IsStopped       := false;
m_IsSuspended  := CreateSuspended;  dwCreateFlags := 0;
  if CreateSuspended  then dwCreateFlags :=4; m_Handle := beginthread(nil,0,@GDKThread_Entry,Self,dwCreateFlags,m_ThreadID);
end;destructor TGDKThread.Destroy;
begin
  try
CloseHandle(m_Handle);
m_Handle :=0;
  except
end;
m_ThreadID := 0;
end;procedure TGDKThread.MainRun;
begin
RunBefore; while(true) do
  begin
Sleep(10); //Sleep在子类内部去做!!
if m_IsStopped then
begin
RunAfter;
break;
end;
    //执行主循环!!!
Run;
end;
  
m_IsOutOfRun := true;//标记线程已经退出了主循环体end;procedure TGDKThread.Resume;
begin
if (m_IsSuspended) then
begin
ResumeThread(m_Handle);
m_IsSuspended := false;
  end;  
end;procedure TGDKThread.Suspend;
begin
if (not m_IsSuspended) then
begin
SuspendThread(m_Handle);
m_IsSuspended := true;
end;
end;procedure TGDKThread.Stop;
begin
  m_IsStopped := true;
end;function TGDKThread.WaitFor(ATimeout: Cardinal): Integer;
var
  _T0 : Cardinal;
begin
  Result := -1;  _T0 := GetTickCount;
  while (true) do
  begin
    if IsOutOfRun then
    begin
      Result := 1;
      break;
    end;    if GetTickCount - _T0 > ATimeout then break;    Sleep(10);
  end;
end;procedure TGDKThread.Run;
beginend;procedure TGDKThread.RunBefore;
beginend;procedure TGDKThread.RunAfter;
beginend;  
////////////////////////////////////////////////////////////////////////////////end.

解决方案 »

  1.   

    哈哈,真快啊说明:  1.如果你想在进入线程循环前做什么事情,请重载RunBefore的方法。同样,如果你要退出时释放什么东西,请重载RunAfter方法。
      2.如果你在线程中处理界面,请你自己binding一个HWND,让线程抛出你自己的消息来,而窗体界面来处理相关界面。所以,我就不给你封装所谓的Synchronize了,嘿嘿。
      3.释放的时候,推荐的方法是这样:procedure TTCPClientTestPool.Notify(Ptr: Pointer;  Action: TListNotification);
    var
      myTCPClient:TGDKThread;  _ret : Integer;
    begin
      if Action = lnDeleted then
      begin
        myTCPClient := Ptr;    myTCPClient.Stop;    _ret := myTCPClient.WaitFor(500);    if _ret =1 then
          myTCPClient.Free
        else
        begin
          TerminateThread(myTCPClient.Handle,0);
        end;
      end;  inherited;
    end;
    大意是这样的,线程真的退出了,肯定IsoutOfRun为True,所以我直接Free就可以了,否则,强杀!嘿嘿。   4. 找不到C++下的_beginthreadex方法,勉强使用beginthread,嘿嘿。
     
      

  2.   

    还有最最重要的一点,你在线程中真正要做的地方,要重载Run,而且这个Run中,只要你做的事情就行了,不要加上While(true)这样的死循环。嘿嘿
    为什么要写这样的一个类呢?
      1.delphi自带的是重量级的,俺们的这个是轻量级的,至少杀起来快,嘿嘿,好控制。
      2.从gdk for C++代码中翻译一下的,嘿嘿,好玩!
      

  3.   

    2.如果你在线程中处理界面,请你自己binding一个HWND,让线程抛出你自己的消息来,而窗体界面来处理相关界面。所以,我就不给你封装所谓的Synchronize了,嘿嘿。 
    ==================
    消息处理接口都没有,真的只要binding一个HWND就可以完成消息处理了?
      

  4.   

    嗯,既然提供了这样的hwnd,还是要提供一个消息处理的地方
      

  5.   

    定义时:  TGDKTCPClient  =  class(TGDKTCPClientSocket)
      private    //////
        m_WindowHandle       : HWND;            //绑定的输出口;
      public
        //设置对外输出口;
        procedure   SetWindowHandle(handle:HWND);
      end;代码:
       procedure TGDKTCPClient.SetWindowHandle(handle: HWND);
       begin
         m_WindowHandle := handle;
       end; 线程的RUN中的一段:
         、、、、、、、、、
         
          if (m_WindowHandle>0) and IsWindow(m_WindowHandle) then
          begin
            SendMessage(m_WindowHandle,WM_GDKTCPIO,0,Integer(@S));
          end;
     
    界面中处理消息的部分:procedure TForm1.WndProc(var Mess: TMessage);
    var
      S : String;
      P : ^String;
    begin
        case  Mess.Msg of
          WM_GDKTCPIO:
             begin
              if not CheckBox_NOShowMsg.Checked then
              begin            P   := Pointer(Integer(Mess.LParam));
                S := P^;
                try
                  if  RzRichEdit1.Lines.Count>10000  then RzRichEdit1.Clear;              if CheckBox_Color.Checked then
                  begin
                    RzRichEdit1.SelStart := length(RzRichEdit1.Text);
                    if Mess.WParam=0 then  //说明是发送的;
                      RzRichEdit1.selAttributes.Color :=   clGreen
                    else
                      RzRichEdit1.SelAttributes.Color := clYellow;
                  end;              RzRichEdit1.Lines.BeginUpdate;
                  RzRichEdit1.Lines.Add(S);
                  RzRichEdit1.Line := RzRichEdit1.Lines.Count;
                  RzRichEdit1.Lines.EndUpdate;
                except
                end;
               end; 
            end;
        end;  inherited;
    end;