2012-10-23 48 views

回答

4

從Indy向VCL線程寫東西的方式也是一樣,從其他地方寫入東西到VCL線程。常用選項包括TThread.SynchronizeTThread.Queue

修改獨立的TBitmap不應該要求與主線程同步。您可以從任何您想要的線程修改它,只要您一次只從一個線程進行修改即可。您可以使用標準同步對象(如關鍵部分和事件)來確保一次只有一個線程使用它。

+0

我做了Id.notify梅索德調用內部的所有VCL的東西,但只適用80%成功... – user1769184

+0

[code] procedure TServerMainForm.IdTCPServerExecute(AContext:TIdContext); var .... begin /// /// TIdNotify.NotifyMethod(ShowStartServerMessage); ...... – user1769184

+0

'TIdNotify.NotifyMethod'異步運行,因爲它只不過是調用'TThread.Queue'。難道20%你想要做的事情需要同步訪問VCL嗎? –

2

同步的最佳方式是創建並使用TidNotify後代。

定義一個tidnotify後代和vcl proc這樣與適當的私人領域。

TVclProc= procedure(aBMP: TBitmap) of object; 

TBmpNotify = class(TIdNotify) 
protected 
    FBMP: TBitmap; 
    FProc: TVclProc; 
    procedure DoNotify; override; 
public 
    constructor Create(aBMP: TBitmap; aProc: TVclProc); reintroduce; 
    class procedure NewBMP(aBMP: TBitmap; aProc: TVclProc); 
end; 

然後實現它像這樣

{ TBmpNotify } 

constructor TBmpNotify.Create(aBMP: TBitmap; aProc: TVclProc); 
begin 
    inherited Create; 
    FBMP:= aBMP; 
    FProc:= aProc; 
end; 

procedure TBmpNotify.DoNotify; 
begin 
    inherited; 
    FProc(FBMP); 
end; 

class procedure TBmpNotify.NewBMP(aBMP: TBitmap; aProc: TVclProc); 
begin 
    with Create(aBMP, aProc) do 
    begin 
    Notify; 
    end; 

end; 

然後從那裏FVclBmpProcis一個私有字段指向程序

server.execute(...) 

這樣稱呼它

procedure TTCPServer.DoExecute(aContext: TIdContext); 
var 
    NewBMP: TBitmap; 
begin 
    TBmpNotify.NewBMP(NewBMP, FVclBmpProc); 
end; 

在表格上hat匹配TVclProc的參數簽名。該字段應該在創建之後和啓動服務器之前通過服務器對象上的屬性進行設置。

表單上的方法可以自由使用它接收到的位圖,而不用擔心通過訪問VCL控件創建的線程爭用,死鎖和其他缺陷而無需同步。

+0

感謝Mike,我將在我的程序中測試該代碼; Delphi和INDY 10的stackoverflow上現在有許多有用的代碼sniplets;有人應該將其複製到E書:-) – user1769184

0

一個簡單的PostMessage的(線程內)和處理消息(線程外)是必要的,使UI更新...