最近使用ClientSock、ServerSock来做个通信程序。我在ClientSock.ClientSocketRead中写了一个死循环来读取服务器端发来的数据,并根据自己定义的协议来进行分析和处理。
由于没有采用线程技术,所以虽然运行起来图像和消息都可以保存,但象死机了一样...郁闷死了。请问各位路过的和飘过的老大,怎么把我写好的ClientSocketRead事件程序写到线程里执行?谢谢!!procedure TfrmClientMain.ClientSocketRead(Sender: TObject;Socket: TCustomWinSocket);
begin
   //Read中的代码大致结构如下,希望在线程中执行代码
   Stream   :=   TMemoryStream.Create;
   try
     isImage := false ;  //图片
     isMsg   := false;   //消息
     while   True   do   //死循环读取端口数据,且永不退出
     begin
         nReceived   :=   ClientSocket.Socket.ReceiveBuf(Buffer,   ClientSocket.Socket.ReceiveLength);
         if nReceived >0 then
         begin
           //分析和处理过程
           ...
         end;
     end;
   finally
     stream.Free;
   end;
   //结束
end;非常着急。谢谢大家了!!

解决方案 »

  1.   

    把ClientSocket移动线程当中去。不过线程当中要提供消息循环。
      

  2.   

    给你做成了线程,不过分要给我哟!
    unit Unit2;interfaceuses
      Classes,SysUtils,ScktComp;type
      ClientSocketThread = class(TThread)
      private
        { Private declarations }
        CS: TClientSocket;
        stream:TMemoryStream;
        procedure CSRead(Sender: TObject; Socket: TCustomWinSocket);
      protected
        procedure Execute; override;
      public
        constructor Create;
      end;implementationconstructor ClientSocketThread.Create;
    begin
    inherited Create(True);
    CS:=TClientSocket.Create(nil);
    FreeOnTerminate:=True;
    cs.OnRead:=CSRead;
    Suspended := false;
    end;procedure ClientSocketThread.CSRead(Sender: TObject;
      Socket: TCustomWinSocket);
    var
    nReceived:integer;
    buffer: array[1..256] of byte;
    begin
    //Read中的代码大致结构如下,希望在线程中执行代码
            nReceived  :=  CS.Socket.ReceiveBuf(Buffer,CS.Socket.ReceiveLength);
            if nReceived >0 then
            begin
              //分析和处理过程
              //...
            end;
      //结束 
    end;procedure ClientSocketThread.Execute;
    begin
      { Place thread code here }
      try
      Stream  :=  TMemoryStream.Create;
      CS.Port:=7000;
      cs.Host:='127.0.0.1';
      cs.Active:=true;
      while (not Terminated)and cs.Active do  //死循环读取端口数据,且永不退出
        begin
        sleep(1);
        end;
      finally
      cs.Active:=false;
      cs.Free;
      stream.Free;
      end;
    end;end.
      

  3.   

    //非阻塞模式,直接为TSocketThread.Socket.OnXXX设置相应的事件处理过程即可。
    unit Unit2;interface
    uses
      Classes,ScktComp;type
      TSocketThread = Class(TThread)
        private
          FSocket: TClientSocket;
        protected
          procedure Execute;override;
        published
          property Socket: TClientSocket read FSocket;
        public
          constructor Create(CreateSuspended: Boolean);
          destructor Destroy;override;
      End;implementation
    uses
      Windows, Messages;
    constructor TSocketThread.Create(CreateSuspended: Boolean);
    begin
      Inherited Create(True);
      FSocket := TClientSocket.Create(Nil);
      FSocket.ClientType := ctNonBlocking;//非阻塞
      if Not CreateSuspended then Resume;end;procedure TSocketThread.Execute;
    var
      Unicode: Boolean;
      MsgExists: Boolean;
    begin
      while Not Terminated do
        begin
          if PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE) then
          begin
            Unicode := (Msg.hwnd <> 0) and IsWindowUnicode(Msg.hwnd);
            if Unicode then
              MsgExists := PeekMessageW(Msg, 0, 0, 0, PM_REMOVE)
            else
              MsgExists := PeekMessage(Msg, 0, 0, 0, PM_REMOVE);
            if not MsgExists then continue;
            if Msg.Message <> WM_QUIT then
            begin
              TranslateMessage(Msg);
              if Unicode then
                DispatchMessageW(Msg)
              else
                DispatchMessage(Msg);
            end
            else
              Terminated := True;
          end;
        end;
    end;destructor TSocketThread.Destroy;
    begin
      FSocket.Close;
      FSocket.Free;
      Inherited;
    end;
    end.
      

  4.   

    谢谢大家的关注!我水平有限,请问你们给的这些Unit文件怎么在我的窗口上调用啊?能不能给个详细的步骤和过程?谢谢啦。
      

  5.   

    var
    AThread:ClientSocketThread;AThread:=ClientSocketThread.create;
      

  6.   

    CS.Port:=19697;
    cs.Host:='127.0.0.1';
    cs.Active:=true;跟踪显示cs.Active一直是false。 但我原来的都能正常连接。请问有什么问题吗?
      

  7.   

    unit Unit2;interface
    uses
      Classes,ScktComp;type
      TSocketThread = Class(TThread)
        private
          FSocket: TClientSocket;
        protected
          procedure Execute;override;
        published
          property Socket: TClientSocket read FSocket;
        public
          constructor Create(CreateSuspended: Boolean);
          destructor Destroy;override;
      End;implementation
    uses
      Windows, Messages;
    constructor TSocketThread.Create(CreateSuspended: Boolean);
    begin
      Inherited Create(True);
      FSocket := TClientSocket.Create(Nil);
      if Not CreateSuspended then Resume;end;procedure TSocketThread.Execute;
    var
      Unicode: Boolean;
      MsgExists: Boolean;
      Msg: TMsg;
    begin
      while Not Terminated do
        begin
          if PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE) then
          begin
            Unicode := (Msg.hwnd <> 0) and IsWindowUnicode(Msg.hwnd);
            if Unicode then
              MsgExists := PeekMessageW(Msg, 0, 0, 0, PM_REMOVE)
            else
              MsgExists := PeekMessage(Msg, 0, 0, 0, PM_REMOVE);
            if not MsgExists then continue;
            if Msg.Message <> WM_QUIT then
            begin
              TranslateMessage(Msg);
              if Unicode then
                DispatchMessageW(Msg)
              else
                DispatchMessage(Msg);
            end
            else
              Terminate;
          end;
        end;
    end;destructor TSocketThread.Destroy;
    begin
      FSocket.Close;
      FSocket.ClientType := ctNonBlocking;
      FSocket.Free;
      Inherited;
    end;
    end.
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ScktComp,
      Unit2, StdCtrls, Buttons;type
      TForm1 = class(TForm)
        Button1: TButton;
        procedure FormCreate(Sender: TObject);
        procedure ClientSocketConnect(Sender: TObject; Socket: TCustomWinSocket);
        procedure ClientSocketConnecting(Sender: TObject;
          Socket: TCustomWinSocket);
        procedure ClientSocketDisconnect(Sender: TObject;
          Socket: TCustomWinSocket);
        procedure ClientSocketError(Sender: TObject; Socket: TCustomWinSocket;
          ErrorEvent: TErrorEvent; var ErrorCode: Integer);
        procedure ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
        ST: TSocketThread;
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation
    {$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    begin
      ST.Socket.Port:=19697;
      ST.Socket.Host:='127.0.0.1';
      ST.Socket.Active:=true;end;procedure TForm1.ClientSocketConnect(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
    //连接成功
    end;procedure TForm1.ClientSocketConnecting(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
    //正在连接...
    end;procedure TForm1.ClientSocketDisconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
    //断开了
    end;procedure TForm1.ClientSocketError(Sender: TObject; Socket: TCustomWinSocket;
      ErrorEvent: TErrorEvent; var ErrorCode: Integer);
    begin
    //出错了
    end;procedure TForm1.ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);
    begin
    //有数据到来
    end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      PostThreadMessage(ST.ThreadID, WM_QUIT, 0, 0); //ST.Terminate;
      ST.WaitFor;
      ST.Free;
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
      ST := TSocketThread.Create(false);
      ST.Socket.OnConnecting := ClientSocketConnect;
      ST.Socket.OnConnect := ClientSocketConnect;
      ST.Socket.OnDisconnect := ClientSocketDisconnect;
      ST.Socket.OnRead := ClientSocketRead;
      ST.Socket.OnError := ClientSocketError;
    end;end.
      

  8.   

    可以用indy里的idTcpServer加上一个IdThreadMgrDefault可实现多线程