为什么在线程中调用时间控件会不执行呢? procedure Tkk.Timer1Timer(Sender: TObject); 
begin 
form1.memo1.lines.add('aa'); 
end; 
procedure Tkk.Execute; 
var 
Time:TTimer; 
begin 
{ Place thread code here } 
Time:=TTimer.Create(nil); 
Time.Enabled:=True; 
Time.Interval:=1; 
Time.OnTimer:=Timer1Timer; 
end;

解决方案 »

  1.   

     线程启动了没? Tkk是线程吧.... 你在哪启动的线程.. 
    应该在Form1下启动线程
    var 
      thread1: Tkk;
    thread1 := Tkk.Create(False);
    这样就执行Tkk.Execute
      

  2.   

    参考3楼
    http://topic.csdn.net/u/20081218/15/28716f7e-d780-4384-a148-c354d85866ce.html
      

  3.   

    while GetMessage(MsgRec, 0, 0, 0) do begin
            TranslateMessage(MsgRec);
            DispatchMessage(MsgRec)
          end;VCL消息处理^_^
      

  4.   

    将Time:TTimer;
    改为线程的私有变量
    在线程创建时,对Time的事件赋值
      

  5.   


    如果在一创建线程的时候就创建Time的话会出现以下问题
    constructor Taa.create;
    begin
      Time:=TTimer.Create(nil); //主要是在创建线程时创建时钟。。要不然可能无法执行他
      Time.Enabled:=false;
      Time.OnTimer:=TimerProc;
      Time.Interval:=1;
      FreeOnTerminate := True; // 自动删除
      inherited Create(False); // 直接运行
    end;
    onTime事件当中就会出现无法将其停止。。
    procedure Taa.TimerProc(Sender: TObject);
    begin
      Time.enabled:=false;  //让他时钟控件只执行这一次      问题出在这里,如果是开始创建这里就会报错
      form1.memo1.lines.add('aa'); 
    end;
    执行处代码
    procedure Taa.Execute;
    begin
      Time.Enabled:=True;
    end;
      

  6.   

    我把分加高希望有朋友能解释一下为什么不行..
    而僵哥的这一个我不知道怎么用呀procedure TMyThread.Execute;
    begin
      FTimer:=TTimer.Create(nil);
      try
          FTimer.Enabled:=false;//需要用的时候Enabled设置为True即可。
          FTimer.OnTimer:=TimerProc;
          while GetMessage(MsgRec, 0, 0, 0) do begin
            TranslateMessage(MsgRec);
            DispatchMessage(MsgRec)
          end;
          Terminate;
      finally
        FTimer.Free;
      end;
    end;不知道的原因是,你这里只是设置了一个消息循环。可是时钟却并没有执行呀。。
      

  7.   

    //你Timer.Enabled:=False了!procedure TMyTest.Execute;
    var
      Msg: TMsg;
    begin
       FTimer:=TTimer.Create(nil);
       try
         FTimer.Enabled:=True;
         FTimer.Interval:=5000 ;
         FTimer.OnTimer:=TimerProc;
         while GetMessage(Msg, 0, 0, 0) do begin
            TranslateMessage(Msg);
            DispatchMessage(Msg)
          end;
          Terminate;
       finally
         FTimer.Free;
       end;
      { Place thread code here }
    end;
      

  8.   

    对于11楼的问题,在僵哥在3楼贴的URL中已有说明!
    你在构造函数中创建Timer,相当于你在主线程中创建的Timer!
    //看看线程类的封装FHandle := BeginThread(nil, 0, @ThreadProc, Pointer(Self), CREATE_SUSPENDED, FThreadID);@ThreadProc为回调函数function ThreadProc(Thread: TThread): Integer;
    begin
      try
        if not Thread.Terminated then
        try
          Thread.Execute;//从这里可以看出,只有Execute中执行的东西才有堆与栈(TLS),并且系统为该线程创建一个单独的消息队列,通过Getmessage与Dispatch来分发,派送消息,这样的话,在时钟到期时,就会向该线程队列发送一个WM_TIMER消息,并由在线程中实现的消息处理器来接收!
        except
     
        end;
      

  9.   

    这里设置Enabled为false是因为示例代码当中当时并没有启用Timer,应该注意到的是包括Interval也没有设置,当你需要的时候外部线程就可以通过相应的方法设置Interval并启用Timer达到目的。该代码主要还是演示如何使用线程内的Timer.
      

  10.   

    如果像这样的写的,程序只执行一次,而为什么当中的会出现退出线程现像呢?procedure TMyThread.Execute; 
    var
      i:integer;
    begin 
      for i:=0 to memo1.lines.count-1 do //这里本来有三条信息,应该要循环三次的
      begin
      FTimer:=TTimer.Create(nil); 
      try 
          FTimer.Enabled:=true;//需要用的时候Enabled设置为True即可。 
           FTime.Interval:=1;   
           FTimer.OnTimer:=TimerProc; 
          while GetMessage(MsgRec, 0, 0, 0) do begin //当我像这样写入后,当FTimer返回值后,线程就全部退出,
            TranslateMessage(MsgRec);               //不再执行for循环了,,这是为什么呢  
            DispatchMessage(MsgRec) 
          end; 
          Terminate; 
      finally 
        FTimer.Free; 
      end; 
     end;
    end; 
      

  11.   

          FTimer.Enabled:=false;//先设置为False,因为这个时候还没有OnTimer处理过程 
           FTime.Interval:=1;   
          FTimer.OnTimer:=TimerProc; 
          FTimer.Enabled:=true;//这里再恢复。
      

  12.   

    另外,不是循环3次,这种使用方法是错误的。使用Timer就没必要使用循环。要对Memo进行操作,应该是在OnTimer事件的处理例程当中。
      

  13.   

    while GetMessage(MsgRec, 0, 0, 0) do begin //当我像这样写入后,当FTimer返回值后,线程就全部退出,
            TranslateMessage(MsgRec);               //不再执行for循环了,,这是为什么呢  
            DispatchMessage(MsgRec) 
          end; 那么为什么当消息执行完后,他后面的那些代码就不会执行了呢?
      

  14.   

    确定线程退出了?还是因为没有消息到达,而被阻塞在GetMessage当中?正常情况下,仅当收到WM_QUIT消息才会使得GetMessage返回False而中断while循环,所以线程并不能象没有消息循环那样一个Terminate而退出,而是需要使用PostThreadMessage(ThreadId,WM_Quit,0,0)来退出线程。
      

  15.   

    lz的21樓代碼有問題。挑重點說:
    如果程序沒有對此線程投遞消息,那么,你的消息循環處理并不會被處理,直接執行了線程的terminate
      

  16.   


    已经投递过去,而且也执行了。。但他就是不执行下面的代码
    僵哥,我不知道怎么说得清楚,所以刚刚去整个动画。麻烦你看看是什么原因
    http://mm.nishishu.cn/123/mm/aa/untitled.swf希望这样看你能明白我说的,我的表达能力不好,,
      

  17.   

    getMessage的返回值可能為 TRUE, FALSE, or -1. 應該要避免這樣的寫法:while (GetMessage( lpMsg, hWnd, 0, 0)) do ...  
     如果返回值為 -1 這樣也會導致線程中止.
      

  18.   

    而socket创建的线程也并没有终止,很明显是没有执行下面的代码造成的错误
      

  19.   

    你的Interval设置可能过小,单位是毫秒,所以,你如果要设置为1秒的话,应该要剩以1000。
      

  20.   

    我看了你的動畫
    你用while not terminated do 循環,我認為在這后面寫任何代碼是沒有意義的。從你代碼看,我猜:你socket的開啟是在線程當中的。
      

  21.   

    线程当中使用TClientSocket/TServerSocket等等几乎所有消息驱动的控件都可以按类似的方法处理,此时的Execute写法跟以往的写法是有所差别的:原来的while Not Terminated循环需要替换成上面那个GetMessage的循环,其它的所有任务递交都通过发送消息的方式来完成。消息可以通过有窗体的消息,然后在特定的窗体上面处理,也可以在GetMessage取得消息之后直接处理(不调用TranslateMessage+DispatchMessage)
      

  22.   


    本来我看了上几次有一个贴子也是一样,要在当中放入判断传递过来的值,如果接受到值就不再执行此语句,但是问题是,站点的大小不一,接受的值也不一样,而且每一个站点返回信息的时间也是不相同的,还有一点就是,每一次发送的到网页的时候是分二段接收的,第一段是请求,请求完成后,你才可以发第二条信息,所以每一次他都会返回第一条的请求信息,所以不知道有没有办法让他接收完整的值后退出这个循环然后执行下面的语句。。刚刚的视频
    http://www.bokelawyer.com/images/asp.gif
      

  23.   


    while not Terminated do
      begin
        if urlpostxx='' then  //如果不加这一句的话会造成他自动退出整个线程.也就是无法再post下一条了
        begin
          try
            GetMessage(MsgRec, 0, 0, 0);
            TranslateMessage(MsgRec);
            DispatchMessage(MsgRec);
          except
            Timeboolean:=True; //信号
          end;
        end
        else
         break; 
      end;  如果我这样写的话,会接收不了返回来的值就退出了。。如果我在当中设置一个sleep(100)时间,就能接收到部份值,有人会说你可以把时间停一点,但是有的站点是很慢的,你不确定他什么时间能返回值给你,所以我现在只能在这个循环消息下手。或者有没有其他的方法可以解决这个Thread线程中用socket控制post网页的问题...
      

  24.   

    Post出去以后,就只需要等触发OnRead事件,然后在该事件当中判断是否接收完成,如果没有就不理会,后续数据到来之后会触发OnRead消息的。比如TClientSocket,本身就有一个Data属性是一个留给用户使用的指针,可以用它来缓存前面收到的数据,然后只管按数据流顺序解析HTTP协议。
      

  25.   


    关于这一位朋友说的我已经在前天晚上实验过了,但是却不行
    原因在于,程序还是只返回一半的值
    procedure TpostTj.ClientSocket1Disconnect(Sender: TObject;
      Socket: TCustomWinSocket);
    begin                               
      if Pos('utf',urlpostxx)>0 then
        urlpostxx:=utf8toansi(urlpostxx);
      urlpostxx:='断'+urlpostxx;
      abcxdindex.statusbar1.Panels[3].Text:='与服务器'+clientsocket1.Address+'断开连接';
    end;原因可能是还没有接收完他就结束了。。
      

  26.   

    估计你可以参考我以前的处理方式(C++代码,跟Delphi差不太多的)
    http://blog.csdn.net/unsigned/archive/2008/09/22/2960982.aspx
      

  27.   

    建议楼主,还是把想要做的功能详细的列出来,综合起来才好处理,否则一会是线程当中的Timer,一会是线程中使用Socket,到最后却又卡在衔接上面。个人理解是,楼主希望自己写代码来实现对一批地址的HTTP交互(可能是POST也可能是GET),同时希望在交互过程当中实现超时控制。为了达到并行处理,并且相互不受影响,所以希望采用多线程来实现。
      

  28.   


    嗯~我写了一个后台管理器。就是当我有新的文章发布的时候。可以同时发布到其他的网站上去。具体实现功能
      循环取得一条值
        然后开始POST到我要发布的网页(用socket)
    就是这么简单的功能
      

  29.   

    肯定是还要接收返回完整的HTML页面,要不然我怎么判断是否提交成功呢?
         
      

  30.   

    其实在我那份C++代码当中就有演示,那份代码是下载一个Norton的更新包,先到他的发布页面上取得最新的更新包,然后通过解析HTML代码,取得更新包的更新时间(文件名当中包含),然后跟本地的文件进行比较判断是否需要下载更新,如果需要则发起下载请求,然后进行下载。只是这一整个流程都是在主线程当中完成,对于使用多线程的情况,完全可以把里面的代码直接搬移到线程当中去处理(当然,那份代码写得着实很糟糕^_^)。
      

  31.   

    你的程序可以采用一个任务列表加多线程的方式来处理(当然我并不清楚检查发布新文章的站点是否有多个,所以就当多个处理):
    第一个任务都有一个标识,比如
    然后开启有限的几个线程,线程从任务列表当中取得任务,根据任务标识进行处理。对于检查任务,则仅在接收信息完成之后直接生成更新任务,这个相对是比较简单的;对于更新任务,则可能对于socket的处理就要分为两步,第一步是Post,Post结束(HTTP信息发送结束),会有相应的服务器给出的确认包,在收到确认报文之后接着转到第二步,生成一个Get请求并发送出去,然后接收Get应答。当这两步完成之后,就可以继续接任务列表当中读取未处理的任务。
      

  32.   

                     while Pos('</html>',urlpostxx)=0 do
                        begin
                          GetMessage(MsgRec, 0, 0, 0);
                          TranslateMessage(MsgRec);
                          DispatchMessage(MsgRec);
                          Sleep(1000);
                        end;改变循环方式可以吗?不过有的地址只返回</script>之类的信息就没办法。。哎
      

  33.   

    我已经说过了,你要判断你的HTML代码,应该在OnRead事件当中ReceiveText/ReceiveBuf之后进行判断,而不是这里,这里面只需要执行
                         ...//创建所须的对象实例
                         while GetMessage(MsgRec, 0, 0, 0) do begin
                          TranslateMessage(MsgRec); 
                          DispatchMessage(MsgRec); 
                      end;
    至于什么Sleep啥的都不需要。然后只在相应的事件,包括OnRead,以及异常处理的OnError及OnDisconnect当中进行处理。如果怕返回的信息是比较特殊的情况,那么可以设置HTTP头信息Connection: closed,即当HTTP交互完毕,即由服务器来主动断开连接,从而触发OnDisconnect事件,触发相应的异常处理。
      

  34.   

    HTTP交互跟普通的Socket交互没有任何差别,只是其中走的是HTTP协议,所有规则包括消息边界的检查只需要遵循HTTP协议即可。对于最后确认交互(POST)是否成功的GET确认当中,可能返回的是所有的数据,实际上你在OnRead当中取得部分信息能够确认POST成功之后,不需要接收完所有的数据,设置一个标记,直接CloseSocket就可以中断交互,然后继续处理后续任务,或者退出线程。
      

  35.   

    while GetMessage(MsgRec, 0, 0, 0) do
    begin
      TranslateMessage(MsgRec);
      DispatchMessage(MsgRec);
      if (Pos('</html>',urlpostxx)>0) or (Pos('接受错误',urlpostxx)>0) then Break;
    end;            哎,用笨人的方法。。不过还是解决了。   
      

  36.   

    while GetMessage(MsgRec, 0, 0, 0) do 
    begin 
      TranslateMessage(MsgRec); 
      DispatchMessage(MsgRec); 
      if (Pos(' </html>',urlpostxx)>0) or (Pos('接受错误',urlpostxx)>0) then Break; 
    end;如果不加if 那么当他接收完值后,他就会终止线程。。
      

  37.   

    没有必要在这里Pos,而在OnRead/OnError/OnDisconnect当中对应的出错或者处理完成情况下,PostThreadMessage(ThreadId,WM_QUIT,0,0)来完成中断。
      

  38.   

    procedure TpostTj.ClientSocket1Connect(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
      index.statusbar1.Panels[3].Text:='与服务器'+clientsocket1.Address+'成功建立连接';
      dosmemo.Lines.Add('与服务器'+clientsocket1.Address+'成功建立连接');
      Socket.SendText(headbuff);
      Socket.sendtext(contentbuff);
    end;procedure TpostTj.ClientSocket1Connecting(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
      index.statusbar1.Panels[3].Text:='正在与服务器'+clientsocket1.Address+'建立连接';
      dosmemo.Lines.Add('正在与服务器'+clientsocket1.Address+'建立连接');
    end;procedure TpostTj.ClientSocket1Read(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
      index.statusbar1.Panels[3].Text:='正在接收数据';
      urlpostxx:=urlpostxx+socket.ReceiveText;
      if Pos('utf',urlpostxx)>0 then
        urlpostxx:=utf8toansi(urlpostxx);
      dosmemo.Lines.Add(urlpostxx);
    end;procedure TpostTj.ClientSocket1Error(Sender: TObject;
      Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
      var ErrorCode: Integer);
    begin
      ErrorCode:=0;      //注意这一句是屏闭错误的关键;
      urlpostxx:='接收错误';
      index.statusbar1.Panels[3].Text:='无法与服务器'+clientsocket1.Address+'建立连接';
      dosmemo.Lines.Add('无法与服务器'+clientsocket1.Address+'建立连接');
    end;
    我这里是这样写的。。你认为怎么改一下呢?
      

  39.   

    SendText,ReceiveText都有一个返回值需要进一步处理,这个并不能够保证发送完或接收完预期的数据。
      

  40.   

    关于保证发送和接收全部预期数据(除非中途失败)的问题,在相关贴子当中我都有回复过,同时也包括的blog当中的代码,都可以用来作为参考。
      

  41.   

    发送和接收,可以参考下面贴子6楼的代码:
    http://topic.csdn.net/u/20081114/11/091305bd-24cf-4c5c-9083-3993e4d98eae.html