【发布时间】:2014-09-03 10:18:38
【问题描述】:
您好,我对临界区有疑问。我有两个线程scannerThread 和scannerchild 线程。下面提到了Scannerthread 的代码。
procedure ScannerThread.Execute;
var
I: Integer;
ScannerCh: Array of ScannerChild;
IpList: TStringlist;
IPCount: Integer;
begin
IpList:=TStringList.Create;
IF GetNumberOfIpsInRange(Ip_From, Ip_To, IpList) then // Function call that returns iplist if TRUE
begin
Try
if Assigned(LvHosts) then // Clear
LvHosts.Clear;
IPCount := IpList.Count;
SetLength(ScannerCh, IPCount);
I := 0;
repeat
while GetTThreadsCount(GetCurrentProcessId) > tcount do // Tcount is threads to create which is given by user
Sleep(10);
ScannerCh[I]:=ScannerChild.Create(True, IpList[i]);
ScannerCh[I].FreeOnTerminate := True;
ScannerCh[I].LvHostname := LvHosts;
ScannerCh[I].Resume;
Inc(I);
until I = IPCount;
if Assigned(IpList) Then
FreeAndNil(IpList);
except
ShowMessage('Operation Failed');
If Assigned(IpList) Then
FreeAndNil(IpList);
end;
end else
ShowMessage('Invalid Range');
repeat
Sleep(100);
Until GetTThreadsCount(GetCurrentProcessId) = 2;
end;
下面提到了 Scannerchild 的代码
procedure ScannerChild.AddToList;
begin
ListItems1 := LVHostName.Items.Add;
ListItems1.Caption := IPToScan;
ListItems1.SubItems.Add(IPAddrToName(IPToScan));
end;
procedure ScannerChild.AddToList1;
begin
ListItems1:=LVHostName.Items.Add;
ListItems1.Caption := IPToScan;
ListItems1.SubItems.Add('No host found');
end;
procedure ScannerChild.Execute;
Var
ListItems1 : TListItem;
Hostname : String;
begin
Hostname := IPAddrToName(IPToScan);
if Hostname <> EmptyStr then
begin
Synchronize(AddToList);
end else
synchronize(AddToList1);
end;
在这里我得到了输出,但它没有被序列化。就像首先创建的线程不会首先显示。如果我将 ip range 192.168.0.1 设置为 192.168.0.10 那么我应该在 listview 中获得序列化输出,如
192.168.0.1 hostname
192.168.0.2 hostname
192.168.0.3 hostname
.
.
192.168.0.10 hostname
但我没有得到它。我的输出就像
192.168.0.1 hostname
192.168.0.2 hostname
192.168.0.4 hostname
192.168.0.6 hostname
192.168.0.3 hostname
是不是因为我没有使用临界区?如果是,我应该在哪里获取和离开临界区,以便首先创建的线程可以先进入临界区,然后再进入下一个线程。
【问题讨论】:
-
看起来 ScannerChild 正在更新 VCL 控件。您不能在线程中执行此操作。
-
否定。不得从 GUI 线程以外的线程访问 VCL 控件。您的代码很明显违反了该规则。我的另一点是。
-
否定。
ScannerChild类显然派生自TThread。因此它具有FreeOnTerminate、Resume、Execute。因此,ScannerChild.Execute中的代码远离 GUI 线程执行。你最好提供一个完整的程序,适当地减少到最小的样本。还有许多其他问题。 -
实际上谁启动线程并不重要,重要的是代码在哪个线程上下文中运行。要临时切换回 MainThread 上下文,请使用
Synchronize或Queue。 -
您为什么希望这些值以任何特定的顺序到达?你了解线程独立运行吗?
标签: multithreading delphi synchronization delphi-7 critical-section