2012-10-23 45 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更新...