Wiz*_*ard 12 delphi multithreading synchronization delphi-xe
该应用程序是用Delphi XE编写的.
我有两个类,TBoss和TWorker,它们都是基于TThread.TBoss是一个单实例线程,启动后会创建大约20个TWorker线程.
当boss创建一个TWorker实例时,它会为它分配一个调用同步的方法,当Worker完成它正在做的事情时,它会调用这个方法,允许Boss访问Worker上的记录.
但是我觉得这是一个问题,调用synchronize似乎是锁定整个应用程序 - 阻塞主(ui)线程.真的应该只是将该工作者与老板线程同步....
以前我使用消息/打包记录在线程之间发送内容很好.然而,这样做是更清洁和更好....只是非常阻止.
有没有办法在worker中调用Syncronize只等待Boss线程?
我的代码:
type
TWorker = class(TThread)
private
fResult : TResultRecord;
procedure SetOnSendResult(const Value: TNotifyEvent);
....
....
public
property OnSendResult: TNotifyEvent write SetOnSendResult;
property Result : TResultRecord read fResult;
....
end;
...
...
procedure TWorker.SendBossResults;
begin
if (Terminated = False) then
begin
Synchronize(SendResult);
end;
end;
procedure TWorker.SendResult;
begin
if (Terminated = false) and Assigned(FOnSendResult) then
begin
FOnSendResult(Self);
end;
end;
Run Code Online (Sandbox Code Playgroud)
然后在我的Boss线程中,我会做这样的事情
var
Worker : TWorker;
begin
Worker := TWorker.Create;
Worker.OnTerminate := OnWorkerThreadTerminate;
Worker.OnSendResult := ProcessWorkerResults;
Run Code Online (Sandbox Code Playgroud)
所以我的老板然后有一个名为ProcessWorkerResults的方法 - 这就是在Synchronize(SendResult)上运行的方法; 工人
procedure TBoss.ProcessWorkerResults(Sender: TObject);
begin
if terminated = false then
begin
If TWorker(Sender).Result.HasRecord then
begin
fResults.Add(TWorker(Sender).Result.Items);
end;
end;
end;
Run Code Online (Sandbox Code Playgroud)
Ken*_*ite 10
Synchronize专门设计用于在主线程中执行代码; 这就是为什么它似乎锁定一切.
您可以使用多种方式从工作线程到老板线程进行通信:
向每个工作线程添加一个回调,并在创建时从boss线程中分配它.它可以传回任何参数,以及线程ID或其他标识符.
使用PostThreadMessage将工作线程中的消息发布到boss线程 .这里的缺点是boss线程必须有一个窗口句柄(请参阅Delphi帮助中的Classes.AllocateHWnd和David Heffernan在下面的评论).
使用高质量的第三方线程库.请参阅 OmniThreadLibrary - 它是免费的,操作系统,写得非常好.
我的选择将是第三个.Primoz为您完成了所有艰苦的工作.:)
在你的评论之后,这是我的第一个建议.请注意,这是未经测试的,因为编写TBoss和TWorker线程的代码+测试应用程序对于我这一刻的时间来说有点长......我希望它足以给你一个要点.
type
TWorker = class(TThread)
private
fResult : TResultRecord;
fListIndex: Integer;
procedure SetOnSendResult(const Value: TNotifyEvent);
....
....
public
property OnSendResult: TNotifyEvent write SetOnSendResult;
property Result : TResultRecord read fResult;
property ListIndex: Integer read FListIndex write FListIndex;
....
end;
type
TBoss=class(TThread)
private
FWorkerList: TThreadList; // Create in TBoss.Create, free in TBoss.Free
...
end;
procedure TWorker.SendBossResults;
begin
if not Terminated then
SendResult;
end;
procedure TBoss.ProcessWorkerResults(Sender: TObject);
var
i: Integer;
begin
if not terminated then
begin
If TWorker(Sender).Result.HasRecord then
begin
FWorkerList.LockList;
try
i := TWorker(Sender).ListIndex;
// Update the appropriate record in the WorkerList
TResultRecord(FWorkerList[i]).Whatever...
finally
FWorkerList.UnlockList;
end;
end;
end;
end;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7886 次 |
| 最近记录: |