我在做语音叫号的程序,要不停的检测在A表中有没有新的数据,如果有新的数据就把他取出来呼叫然后在通过串口显示在LED上,使用方法是用了两个线程,一个是不停的刷新表里的数据,另一个是把数据取出来呼叫并显示,结果现在就算没数据时候,只检测数据CPU就到了50%,而且在50%检测的时候程序就和死掉一样,谁能解释一下,并写些简单的控制代码

解决方案 »

  1.   

    我不知道楼主的不停检查A表的概念是什么,是不是精确到百分之一秒,对于这样的叫号程序就算延迟2,3秒都没人怪你,所以不需要用线程更加不需要刷这么密,改用TTimer控件做定时刷新数据表就可以了,每秒刷一次,有了就输出叫号
      

  2.   

    对,用触发器才是正道
    为什么呢,很简单,因为如果用TIMER的话,那我们假设如果数据量很大,在30秒里都无法处理完插入的动作话,那么在下一次的时候,很容易出现死锁.
      

  3.   

    也遇到过类似的问题,你的SQL-Server版本是多少,硬件配置如何?关系密切哦,还有,程序和SQL-Server是否是同一台?
    如果是同一台,那赶紧换,升级内存,我们就是这样解决了。
      

  4.   

    另外一种,仍然是使用检测,但不是象楼主这样在原表当中检测,日各月累,原表数据量大,操作需要的资源多。如果没有处理好锁的关系,那么就经常死锁。可以采用触发器,写信息到另外一个“信号”表当中。检测的时候采用readpast(全部都要加锁)。处理完一条删除一条。而检索的密度基本上设置在一秒钟以内就可以了。这样子就不会影响写入操作。而检索到之后放置内存队列当中。然后具体的处理由其他业务线程对队列进行处理。
      

  5.   

    楼主刷数据库的间隔是多少?如果很短,当然CPU占用高....
      

  6.   

    对于刷数据库,我倒是在一个应用当中使用到,不过是存储过程,当中原来的最小间隔设置为0.01秒(waitfor delay N'0:00:0.01'),有强的服务器上CPU占用率很低,但是稍差一点的服务器就可能会占到20%以上。对于外部来操作,倒没有刻意使用短时间间隔来操作。
      

  7.   

    发现执行以下的代码就会使SQL-SERVER的CPU占用到50%还有一个线程也是大概和这个写的差不多执行就没有问题
    procedure displaythread.autonext;
    begin
      With dm.ADOQuery4 do
      begin
        Close;
        SQL.Clear;
        SQL.Add('exec auto_doct_next');
        execsql;
      end;
    end;constructor displaythread.create(abc:boolean);
    begin
      inherited create(false);
     end;procedure displaythread.Execute;
    begin
    while (not terminated) do
    begin
    sleep(10000);
    synchronize(autonext);
    end;
    end;
      

  8.   

    线程执行为什么要用synchronize,而不是在线程里面创建一个私有对象Connection/Command来执行?
      

  9.   

    线程也是我新发现的,我看标准的执行程序上都是用的synchronize,用Connection/Command也可以吗?
      

  10.   

    可以为线程类添加两个私有对象如TDisplayThread = class(TThread)
    ...
    private
      IsOleInitialized:Boolean;
      SQLText    : String;
      Connection : TADOConnection;
      Command    : TADOCommand;//象楼主这样使用存储过程,还可以使用TADOStoredProc
    ...
    protected
      procedure Execute;override;
    public
      constructor Create(   CreateSuspended  : Boolean
                         ;  ConnectionString : String
                         ;  SQLString        : String);
      destructor Destroy;override;
    end;构造函数constructor TDisplayThread.Create(   CreateSuspended  : Boolean
                                      ;  ConnectionString : String
                                      ;  SQLString        : String);
    begin
      Inherited Create(True);//不管是否一开始就需要运行,先暂停(基本要素还没实例化成功)
      IsOleInitialized := False;//要使用ADO,就需要进行COM初始化
      Connection := TADOConnection.Create(Nil);//注意这个Connect的Owner参数传空值
      Command    := TADOCommand.Create(Nil);
      Connection.ConnectionString := ConnectionString;
      Command.Connection := Connection;
      Command.CommandText := 'select ''Test Connection...''';//这是MSSQL可用的测试,不同数据库换之
      try
        Command.Execute;
      except
        //数据库连接失败,这里处理,通常需要抛出异常
      end;
      SQLText := SQLString;
      if Not CreateSuspended then
        Resume;//如果创建即需执行,就执行起来吧
    end;destructor TDisplayThread.Destroy;
    begin
      Command.Free;
      Connection.Free;
      if IsOleInitialized then 
        CoUninitialize;//线程还是有可能会被意外结束的,所以这里加一个保险
    end;
    线程函数procedure TDisplayThread.Execute;
    begin
      CoInitializeEx(nil, COINIT_MULTITHREADED);//COM初始化
      IsOleInitialized := true;
      try
        Command.Text := SQLText;
        while Not Terminated do
          begin
            try
              Command.Execute;
            except
              on E:Exception do
                begin
                  LogException(E);
                end;
            end;
            Sleep(10000);
          end;
      finally
        CoUninitialize;//COM调用结束
      end;end;