MultiThread&界面冻结德尔福

时间:2014-07-22 14:13:03

标签: multithreading delphi memory-leaks interface queue

我正在研究Delphi应用程序和Android应用程序之间的以太网数据传输服务器。 对于数据传输,我使用的是IBM的MQTT协议。

作为年轻的开发者,这个应用程序是我的第一个Real MultiThread应用程序,我的界面有点问题:

当我使用它或不时时,它会冻结很长时间(如果他出去冻结......)。 为了正确使用我的UI,我已经制作了一个非常容易使用我的界面的线程: 当一个Thread想要在我的UI上移动一个东西时,他会调用我的UIGestThread:AddItem的过程 对于不同的接口使用,我有5或6次重载此过程。

这个过程将在一个字符串列表中添加一个包含3个字符串,1个Tobject,一个单词和另一个Object类的记录类型,该列表将由线程在其执行中读取。

当线程在字符串列表中找到一个对象时,他会看到第一个,检查一个字符串,在该字符串中使用该对象。在他调用同步调用的方法后,修改我的UI。

但它冻结,如果有人可以帮助我,谢谢你;) 对不起我的英语,我正在学习;)

编辑1: 在对我的线程进行一点修改后,我发布了新代码,如果它可以提供帮助的话。 这个线程有一个更好的立场,而不是冻结加上界面,并允许在界面上保持响应应用程序的更多操作。

是的,我在这里发生了内存泄漏,我不明白为什么:

我的线程的例子:(我认为它不可用)

// My type of pointer used in the following code:
TIhmActRec = record
public
    sMsg: TMsgString;
    sMsg2: TMsgString;
    sMsg3: TMsgString;
    sTop: TTopString;
    iInteg1,iInteg2,iInteg3:integer;
    bBool:boolean;
    def:TDefHandle;
end;
PTIhmActRec = ^TIhmActRec;

我的应用程序的另一个线程可以调用AddItem来向接口添加订单。 AddItem有8个可能,比如配置订单的3个例子。

procedure TGestionIHMThread.AddItem(s1: String);
var
    str: PTIhmActRec;
begin
    new(str);                   //Create of an new pointer
    str^.sTop := LeftStr(s1, 5);            //Init of value
    ListThreadItem.Add(str);            //Add to a ThreadList 
end;

procedure TGestionIHMThread.AddItem(s1: String; i1, i2, i3: integer);
var
  str: PTIhmActRec;
begin
  new(str);
  str^.sTop := LeftStr(s1, 5);
  str^.iInteg1 := i1;
  str^.iInteg2 := i2;
  str^.iInteg3 := i3;
  ListThreadItem.Add(str);
end;

procedure TGestionIHMThread.AddItem(s1: String; def: TDefHandle);
var
  str: PTIhmActRec;
begin
  new(str);
  str^.sTop := LeftStr(s1, 5);
  str^.def := def;
  ListThreadItem.Add(str);    
end;

Thread在线程列表中添加了一个对象后,Execute过程将获取该对象 并调用程序CallMajIhm(Object)以使用它

procedure TGestionIHMThread.Execute;
var
  str: PTIhmActRec;     //Pointeur for take new item
begin
  repeat
    try
      with ListThreadItem.LockList do
        try
          if (Count > 0) then
          begin
            str := First;       //Take item in pointer
            Delete(0);      //Delete first case of my list
          end
          else
            str := nil;
        finally
          ListThreadItem.UnlockList;
        end;
      if ((str <> nil)) then
      begin
        try
          CallMajIhm(str);      //Launch CallMajIhm
        finally
         str := nil;
        end;
      end;
        sleep(10);
    Except
      //
    end;
  until Terminated;
end;

// CallMajIhm将其他List中的值存入并启动对象询问的过程// Queue下的消息,以便与UI同步。

procedure TGestionIHMThread.CallMajIhm(Messages: PTIhmActRec);
begin
  try
    sTxtCall1 := Messages.sTop;
    ListForQueueIssue.Add(Messages);
    if sTxtCall1 = 'FLBNC' then
    begin
      Queue(CallFMQTTListBoxNrClear);
    end
    else if sTxtCall1 = 'FLBNA' then
    begin
      Queue(CallFMQTTListBoxNrAdd);
    end
    else if sTxtCall1 = 'FLBND' then
    begin
      Queue(CallFMQTTListBoxNrDel);
    end
  finally
    // RAZ des valeurs afin d'etre sur qu'elle ne soit pas réutilisé suite a un bug...
    sTxtCall1 := '';
  end;
end;

//在Queue下调用的每个过程都采用相同的格式:

procedure TGestionIHMThread.CallFMQTTListBoxNrClear;
begin
  try
    trytakeitem;                    //Take the Order
    if PValForQueue.sTop = 'FLBNC' then     //Verify if it's the good order
      if FormTestMQTT.ListBoxnr <> nil then //Verify if the UI's object existing before
        FormTestMQTT.ListBoxnr.Clear;       //Make the Order
  finally
    Dispose(PValForQueue);          //Dispose the Order
    PValForQueue:= nil;             //Forget the Order
  end;
end;

procedure TGestionIHMThread.CallFMQTTListBoxNrAdd;
begin
  try
    trytakeitem;
    if PValForQueue.sTop = 'FLBNA' then
      if FormTestMQTT.ListBoxnr <> nil then
        FormTestMQTT.ListBoxnr.Items.Add(PValForQueue.sMsg);
  finally
    Dispose(PValForQueue);
    PValForQueue:= nil;
  end;

end;

procedure TGestionIHMThread.CallFMQTTListBoxNrDel;
begin
  try
    trytakeitem;
    if PValForQueue.sTop = 'FLBND' then
      if FormTestMQTT.ListBoxnr <> nil then
        if FormTestMQTT.ListBoxnr.Items.IndexOf(PValForQueue.sMsg) <> -1 then
          FormTestMQTT.ListBoxnr.Items.Delete
            (FormTestMQTT.ListBoxnr.Items.IndexOf(PValForQueue.sMsg));
  finally
    Dispose(PValForQueue);
    PValForQueue:= nil;
  end;
end;

//Procedure which take the order in the threadlist : 
procedure TGestionIHMThread.trytakeitem;
var
iCpt : integer;
begin
iCpt:=0;
  with ListForQueueIssue.LockList do
    try
      if (Count > 0) then
      begin
        iCpt:=Count;
        PValForQueue := First;
        Delete(0);
      end
      else
        PValForQueue := nil;
    finally
      ListForQueueIssue.UnlockList;
    end;
end;

// 编辑1: // 我认为原来的问题已经解决但我在这个函数中有内存泄漏:我对Queue的使用是否正确?因为如果线程调用proc&#34; AddItem&#34;太多了,ListForQueueIssue增长,没有安全性,内存泄漏继续增长......

0 个答案:

没有答案