2011-12-17 27 views
-3

有時候這個函數會鎖定我的程序,直到我關閉它纔會凍結。 這裏有什麼問題?德爾福:TThreadList有時會鎖定程序

function del_from_list(id:string):boolean; 
var i : integer; 
begin 
    Result := True; 
    try 
    with global_list.LockList do 
    begin 
     for i:=0 to Count-1 do 
     begin 
     if Tthread_list(Items[i]).id = id then 
     begin 
      Delete(i); 
      break; 
     end; 
     end; 
    end; 
    finally 
    global_list.UnlockList; 
    end; 
end; 

Tthread_list = class 
    public 
    id : string; 
    constructor Create(const id: string); 
    end; 

我添加到列表這樣的:

global_list.Add(Tthread_list.Create('xxx')); 

全局列表是一個全局變量

​​
+0

我認爲沒有理由認爲這應該導致掛起。這是所有的應用程序中的代碼掛起? –

+1

最有可能你有一個典型的死鎖情況,但這個代碼本身不能導致它。某處必須有另一個鎖。 –

+0

您正在刪除列表中的類對象項目,而不先釋放對象。如果因此發生異常,您的程序將被鎖定。雷米(您接受)的答案解決了鎖定問題,但不是主要錯誤。 –

回答

5

你需要調用LockList()它裏面外面try塊來代替,例如:

function del_from_list(const id: string): boolean; 
var 
    List: TList; 
    i : integer; 
begin 
    Result := False; 
    List := global_list.LockList; 
    try 
    with List do 
    begin 
     for i :=0 to Count-1 do 
     begin 
     if Tthread_list(Items[i]).id = id then 
     begin 
      Delete(i); 
      Result := True; 
      break; 
     end; 
     end; 
    end; 
    finally 
    global_list.UnlockList; 
    end; 
end; 
+1

Remy,我同意資源獲取(鎖定)應該在進入try..finally塊之前完成,但是如果資源獲取失敗並拋出,則以另一種方式(OP)應該只會導致問題。刷新我的記憶 - TThreadList.LockList可以拋出異常嗎? – dthorpe

+5

@Remy您是否認爲這種確實正確的更改將會成爲工作應用程序和僵局之間的區別?如果是這樣,你能解釋爲什麼你相信這一點。如果沒有,那麼你爲什麼發佈這個答案?這似乎應該是對我的評論。 –

+0

@dthorpe LockList今天是'TMonitor.Enter(FLock);結果:= FList;'所以它不會拋出,除非存在堆損壞或'TMonitor'中的錯誤。 –

-1

在循環計數錯的方向。當刪除成員時,您必須倒數,而不是最多。

+5

在調用Delete()後使用「Break」時不行。如果從列表中刪除多個項目,則只需要向後循環。 –

+0

是的,這就是爲什麼有一個休息。 – waza123