比如说,某个字符串集合,大约有80个元素,"test","fast","report",.............。
在某个定时器内判断,如果集合中的元素发生了变化,则返回真,否则为假。
这种变化包括在定时器时间片内集合中增加元素(但不会多于85个)、减少元素(但不会少于75个)或替换元素。
请提供最快的判断方法。
注意,定时器时间片大约只有5秒,因此这种判断至少应该在4秒内完成。

解决方案 »

  1.   

    自定义一个类派生与TStrings,加入你的事件:
    OnInsertItem, OnDeleteItem, OnUpdateItem, OnReplaceItem...
      

  2.   

    更高端的办法是利用观察者模式.
    ISubject = interface
    ..................TMyStrings = class(TStrings, ISubject)
    ............把你需要得变化信息的元素变成观察者TMyForm = class(TForm, IObserver)
    .......注册观察者
      

  3.   

    谢谢,老冯思路挺广的,不过可能我的问题没有提准确:
    1、首先这个集合不一定是字符串,也可能是整数或其它基本数据类型,但不是对象;
    2、其次这个集合的获得也是在定时器的时间段内,而且是从数据库通过adoquery获得的。
      

  4.   

    唉,讲穿了就是如何快速判断一个数据集的记录是否发生了变化?
    =========
    这个有两种情况:
    1.数据已经在本地内存,可以利用ClientDataSet的相应事件来处理
    2.数据在后台数据库,由外部改变了数据. 那就需要你把新数据取回来比较原来的数据.
      

  5.   

    其实这个问题也可以扩大到一个ORM(对象关系数据库影射)的问题.当然这个话题又大了.呵呵呵呵.废话说了那么多,还是没有给出具体答案.来! 干正活,把你的实际例子和最具体的要求贴出来吧,看看能不能帮上忙?
      

  6.   

    问题是,通过ado的requery方法定时到服务器取数据,无论数据集发生了增减和替换,好象都不会触发合适的事件。
      

  7.   

    由于没有找到好的办法,我只能判断最后一条记录是否发生变化了.
    .......
      DataModule9.ADOQuery1.sql:='select * from tbdocument order by createtime';
    ........
    var
      LastId:integer;//全局变量
    //定时提示待批阅文件
    procedure TMainForm.Timer2Timer(Sender: TObject);
    var
      id:integer;
      BookMark:TBookMarkStr;
    begin  try
        BookMark:=DataModule9.ADOQuery1.Book;
        DataModule9.ADOQuery1.Requery();
        DataModule9.ADOQuery1.Last;
        id:=DataModule9.ADOQuery1.FieldByName('id').AsInteger;
        DataModule9.ADOQuery1.Book:=BookMark;
      except
      end;
      if DataModule9.ADOQuery1.IsEmpty then exit;
      if id=LastId then exit; //如果没有增加新的批阅文档则退出
      if flashForm=nil then
      begin
        playSound(Pchar(ExtractFilePath(Application.ExeName)+'Global.wav'),   0,   SND_ASYNC   or   SND_FILENAME   or   SND_NODEFAULT);
        flashForm:= TflashForm.Create(self);
        flashForm.ShowModal;
        sfts:=flashForm.ask;  //释放前取得全局变量
        FlashWindow(flashForm.Handle,true);
        FreeAndNil(flashForm);
        Timer2.Interval:=9000;//9秒后再提示
      end;
       if flashForm<>nil then FlashWindow(flashForm.Handle,true);
       playSound(Pchar(ExtractFilePath(Application.ExeName)+'Global.wav'),0,SND_ASYNC or SND_FILENAME or SND_NODEFAULT);
       LastId:=id;   //原来要批阅的文档
    end;
      

  8.   

    建触发器是没办法解决问题的,因为数据集记录虽然发生了增减,但与数据集相关的数据表的记录并不一定甚至没有发生增减,数据集中的记录是按条件取出来的.
    =========================
    这个有两种情况:
    1.数据已经在本地内存,可以利用ClientDataSet的相应事件来处理
    2.数据在后台数据库,由外部改变了数据. 那就需要你把新数据取回来比较原来的数据.
    =========================
    你的情况是哪一种?
    是第一种吗?
      

  9.   

    呵呵, 触发器不光是Insert/Delete 还有Update啊.
      

  10.   

    ClientDataSet1.Modified   ????
      

  11.   

    UpdateStatus。这些都可以考虑一下
      

  12.   

    建一个只有一个一条记录一个整数字段的日志表,在监视的表上建一个触发器,如果一有delete/insert/update,就让日志表字段值增1。在定时器里
    取日志表数据与上次的比较,如果大说明监视表发生了改变。