我现在做了一个即时显示信息的小软件,要求从服务器上即时显示服务端sql2000数据库中的信息,于是采用线程刷新客户端的办法,可这段程序,一会行,一会不行,有时则提:"在异步运行时,操作不能被执行",请各位老兄给指点一下,这样写有什么不对,我对线程不熟悉,原先采用定时器定时刷新,那样系统会占用大量系统资源,软件有假死现象
这是我定义的线程
TTestThread=class(tthread)        //被测试线程,仅仅是将窗体的caption从0变到10000
    protected
    procedure Execute;override;
  end;
  TmThread=class(TThread)           //检测线程,当被侧线程中止时,显示一个对话款
    protected
    procedure Execute;override;
  end;
var
  frmMain: TfrmMain;
  t: TTestThread;
implementationuses ......procedure TTestThread.Execute;  {TTestThread}
var
  i:integer;
begin
  FreeOnTerminate:=True;
  dtmData.adtMsgInfo.requery;     
  dtmData.adtMsgInfo1.requery;
  adtMsgInfo与adtMsgInfo1;         //为sql2000服务器上的同一个表(一个用来显示全部信息,一个用来显示搜索信息)
end;procedure TmThread.Execute;   {TmThread}
begin
  if WaitForSingleObject(t.Handle,INFINITE)=WAIT_OBJECT_0 then
  begin
    Sleep(5000);
    t:=TTestThread.Create(False);
    TmThread.Create(False);
  end;
  //ShowMessage('线程已经中止');
end;
procedure TfrmMain.FormShow(Sender: TObject);  //当开启主窗口时自动定时刷新数据
begin
  t:=TTestThread.Create(False);
  TmThread.Create(False);
end;

解决方案 »

  1.   

    Sleep(5000); 
    5s啊 
    Sleep的时间是不是有点长了 
    你的线程也没有挂起
      

  2.   

    是不是没有用Synchronize进行同步啊
      

  3.   

    在Excute中加一句这个CoUninitialize;
      

  4.   

    还有这个CoInitializeEx(nil, COINIT_APARTMENTTHREADED);放在最前面,上面的放在最后
      

  5.   

    多线程问题,如果有可能,你最好看看孙鑫VC视频教程中讲的多线程那一节,很透彻,虽然不是Delphi的,但都差不多,尤其是原理。http://www.sunxin.org/video/vc.asp
      

  6.   

    好象线程编写时都要用Synchronize进行同步
      

  7.   

    dtmData.adtMsgInfo 可能会被不止一个线程同时用到的话,就要+Synchronize进行同步,不然报错。好像是因为D的VCL是 线程不安全的...
      

  8.   

    为什么要在一个线程中创建另一个线程执行一次性动作?
    procedure TmThread.Execute;  {TmThread} 
    begin 
      if WaitForSingleObject(t.Handle,INFINITE)=WAIT_OBJECT_0 then 
      begin 
        Sleep(5000); 
        t:=TTestThread.Create(False); 
        TmThread.Create(False); 
      end; 
      //ShowMessage('线程已经中止'); 
    end; 一条条语句来分析:
    if WaitForSingleObject(t.Handle,INFINITE)……
    这里t如果是nil呢?
    t:=TTestThread.Create(False); 你的TTestThread只执行一次操作,这个操作为何不直接写为TmThread的一个函数(/过程)?
    TmThread.Create(False); 这个东东干啥?
    似乎你的思路没理好。
      

  9.   

    没有用Synchronize同步吧?
    还有不要直接调用外部的数据集,有用到数据集的话应该在线程里创建数据集
      

  10.   

    Synchronize是TThread类为了同步VCL界面的操作而加入的.
    看过TThread类的源码就可以知道它所同步的过程代码将会被放到主线程执行.以便不会同时出现多个线程
    同时操作一个界面上的元素.
    我觉得楼主的这个同步方式看着很别扭.你可以用信号量来做同步的啊(参见CreateSemaphore,OpenSemaphore及WaitForSingleObject).
      

  11.   

    一般可以按下面的方式设计线程:
    while not terminated do 
    begin
      if 情况A标志 then
      begin 
        处理情况A;
        情况A标志 := false;
      end;  记时;
      if 时间到 then
      begin
        处理情况B;
        重启记时;
      end;
    end;在你的例子中,上面的情况A可以是某些操作数据库的操作;情况B则是你定时的显示操作。我一般的操作方式是:建立一个任务列表,有任务就往列表中加,线程的处理则是循环检测任务是否为空,不为空则取出任务处理,进行相关处理。这就是“生产-消费者”模式。保证各任务是排队处理,不会造成某项任务没完成,另一个任务立即去制造混乱(举例:比如你两个处理用到同一个组件,一个要求查询,一个要求插入,就会造成冲突……)。
    当然,同步,是要做的。
    你主要的问题是思路没理清。
      

  12.   

    用创建一个线程操作数据库,有状态变化时用消息传递.TZDBThread=class(TThread)procedure Execute;override; end;
    procedure TZDBThread.Execute;
    begin
      while Trud do
      begin
       读取数据库
      end;
    end;但最好的办法是不要数据库绑定,创建一个列表保存返回结果procedure TZDBThread.Execute;
    var
     ADOQ:TADOQuery
    begin
      创建ADOQ
      while Trud do
      begin
       读取数据库
       将结果保存在一个列表中.如果不同时给窗体发送消息,将结果显示
       Postmessag(窗体Handle ,自己定义的消息,0,0);
        如果相同则不发送消息.
       Sleep(刷新的时候间隔);
      end;
      ADOQ.Free;
    end;