说明:把多个数据分别传到多个线程中,出错了。例如:现有一个字符串数组,里面有三个字符串,这是我要创建3个线程,分别处理这个字符串。但是在我写的代码中,所有的线程只处理了字符串数组中的最后一个字符串。为什么呀????
主要是下面的 for 循环和ThreadCopyAddress.Execute过程代码如下:
unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    Button1: TButton;
    ListBox2: TListBox;
    procedure Button1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    OldSL: TStringList;
    CopyEnd: Boolean;
    S: String;
  end;var
  Form1: TForm1;implementation
uses Unit2;
{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
var
  CopyAddress,CopyAddress1:ThreadCopyAddress;
  i: Integer;
begin
    OldSL := TStringList.Create;      OldSL.Assign(ListBox1.Items);      for i:=0 to OldSL.Count-1 do   
      begin
        S := Form1.OldSL.Strings[i]; 
        CopyAddress := ThreadCopyAddress.Create(false);
      end;
end;

unit Unit2;interfaceuses
  Classes;type
  ThreadCopyAddress = class(TThread)
  private
    { Private declarations }
    procedure ClearOldSL;
  protected
    procedure Execute; override;
  end;implementation{ ThreadCopyAddress }
uses Unit1;
procedure ThreadCopyAddress.ClearOldSL;
begin
  Form1.OldSL.Clear;end;procedure ThreadCopyAddress.Execute;
var
  i: Integer;
begin
  { Place thread code here }  Form1.ListBox2.Items.Add(Form1.S);
  Synchronize(ClearOldSL);
end;end.

解决方案 »

  1.   

    uses Unit1;
    procedure ThreadCopyAddress.ClearOldSL;
    begin
      Form1.OldSL.Clear;end;procedure ThreadCopyAddress.Execute;
    var
      i: Integer;
    begin
      { Place thread code here }  Form1.ListBox2.Items.Add(Form1.S);
      Synchronize(ClearOldSL);
    end;这段代码明显有问题,每个线程当然只处理了一个相同的S啊!  Synchronize(ClearOldSL);
      

  2.   

    >> Form1.OldSL.Clear;
    这句有问题
    修改为:
     Form1.ListBox2.Items.Add(Form1.S);
     sleep(1000); // 可适当减小这个值
      Synchronize(ClearOldSL);
      

  3.   

    不过,老实说,你的代码由问题,最好就是:去掉这句:Synchronize(ClearOldSL);
      

  4.   

    象这种多线程访问一个数据的情况一定要进行同步的。要给数组的每一项做记号,来说明这一项是否被处理了,先将 每个标志位初始化为 0 当有线程选择了它的时候用 InterlockedIncrement 将标志位设置为1或者用临界区也可以。
      

  5.   

    我之前试了一下,也是没有用;去掉这句:Synchronize(ClearOldSL),没有用;
    假如用 sleep(1000)话,这样性能就很差了?这个方法不可取
      

  6.   

    unit unit1
    ......procedure TForm1.Button1Click(Sender: TObject);
    var
      CopyAddress,CopyAddress1:ThreadCopyAddress;
      i: Integer;
    begin
      OldSL := TStringList.Create;
      OldSL.Assign(ListBox1.Items);  for i:=0 to OldSL.Count-1 do
      begin
        S := Form1.OldSL.Strings[i];
        CopyAddress := ThreadCopyAddress.Create(TRUE);
        CopyAddress.InStr := S;
        CopyAddress.Resume();
      end;
    end;
    unit Unit2;interfaceuses
      Classes;type
      ThreadCopyAddress = class(TThread)
      private
        { Private declarations }
        procedure ClearOldSL;
      protected
        procedure Execute; override;
      public
        InStr:string;
      end;implementation uses Unit1;{ Important: Methods and properties of objects in visual components can only be
      used in a method called using Synchronize, for example,      Synchronize(UpdateCaption);  and UpdateCaption could look like,    procedure hreadCopyAddress.UpdateCaption;
        begin
          Form1.Caption := 'Updated in a thread';
        end; }{ hreadCopyAddress }procedure ThreadCopyAddress.ClearOldSL;
    begin
       Form1.ListBox2.Items.Add(InStr);
    end;procedure ThreadCopyAddress.Execute;
    begin
      { Place thread code here }
      Synchronize(ClearOldSL);
    end;end.