用于ip扫描程序的多线程的关键部分

gas*_*rez 1 delphi multithreading synchronization delphi-7 critical-section

您好我对关键部分有疑问.我有两个线程scannerThread和scannerchild thread.Code for 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;
Run Code Online (Sandbox Code Playgroud)

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;
Run Code Online (Sandbox Code Playgroud)

这里我得到输出但它没有序列化.像首先创建的线程一样,不会首先显示.如果我把ip范围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
Run Code Online (Sandbox Code Playgroud)

但我没有得到它.我的输出就像

    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
Run Code Online (Sandbox Code Playgroud)

那是因为我没有使用临界区吗?如果是的话,我应该在哪里获取并留下关键部分,以便首先创建的线程可以首先进入关键部分,然后像下一个进入下一个线程.

Dav*_*nan 5

线程并行执行,彼此独立.除非您在线程之间强制执行某些同步或序列化,否则它们完成任务的顺序是不可预测的.

我建议您不要尝试按特定顺序更新UI,因为这样做会阻碍扫描的性能,或者使代码更复杂.

我有很多评论:

  1. 将扫描与UI分开.这样的设计更清晰,让您可以独立地专注于每个方面.实现此目的的方法是将扫描结果存储在非可视结构中,然后安排GUI呈现此结构的视图.
  2. 一旦启动线程,不要在终止线程上保留free的引用,因为引用可能随时变得陈旧.
  3. 不要创建线程来处理单个地址.使用线程池.
  4. 别睡觉
  5. 你的代码泄露了IpList.学习如何使用finally.