Threadオブジェクトからformオブジェクトにアクセスできない

解決


ヤマダ  2009-02-10 09:56:06  No: 33301  IP: [192.*.*.*]

ヤマダです。
宜しくお願いします。

D7 + windows vistaです。

簡単に書きますがあるスレッドオブジェクトから
フォームオブジェクトの(fileList:TStringList)にアクセスします。
    *Synchronizeメソッドで

threadCreate(false)する直前では、frmMain.fileList.count = 8です。
しかしなぜかスレッドオブジェクトからアクセスすると
frmMain.stringlist.count = 0になっています。

ただstringlist.clearをするようなコードは、存在していません。

なぜなのでしょうか?

宜しくお願いいたします。

編集    削除
にしの  2009-02-10 23:29:10  No: 33302  IP: [192.*.*.*]

再現しません。
# Delphi7+XP
どういうコードを書いているのでしょうか。

# 再現しないサンプル

unit uMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TMyThread=class(TThread)
  protected
    procedure Execute; override;
  public
    procedure DoRefresh;
  end;

  TForm1 = class(TForm)
    AddButton: TButton;
    StartButton: TButton;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure AddButtonClick(Sender: TObject);
    procedure StartButtonClick(Sender: TObject);
  private
    { Private 宣言 }
    MyThread: TMyThread;
  public
    { Public 宣言 }
    fileList: TStringList;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
  fileList := TStringList.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  if Assigned(MyThread) then
  begin
    MyThread.Terminate;
    MyThread.Free;
  end;
  fileList.Free;
end;

procedure TForm1.AddButtonClick(Sender: TObject);
begin
  fileList.Add('Flie' + IntToStr(fileList.Count));
end;

procedure TForm1.StartButtonClick(Sender: TObject);
begin
  MyThread := TMyThread.Create(true);
  MyThread.Resume;
end;

procedure TMyThread.Execute;
begin
  while not Self.Terminated do
  begin
    Sleep(1000);
    Synchronize(DoRefresh);
  end;
end;

procedure TMyThread.DoRefresh;
var
  text: String;
begin
  text := DateTimeToStr(Now);
  text := text + ' ' + IntToStr(Form1.fileList.Count);
  Form1.Label1.Caption := text;
end;

end.

編集    削除
ヤマダ  2009-02-11 02:17:58  No: 33303  IP: [192.*.*.*]

ヤマダです。
にしのさん、ご返信ありがとうございます。

下記にソースを抜粋して添付いたします。
抜粋の仕方が悪かった場合は、お手数ですが
ツッコミお願い致します。

unit MAIN;

  
  TMainForm = class(TForm)
    miImportClick(Sender: TObject);
    procedure miImportClick(Sender: TObject);
  private
    { Private declarations }
    FThreadImport:TImportFileThread;

    //対象ディレクトリのjpgファイルを取得
    procedure getImportList(var sList:TStringList;dir:String);
    //Import対象のファイル名でtreeNodeを作成しtreeviewに登録する。
    procedure addNodeforPic();
    procedure importDone(sender:TObject);
  public
    { Public declarations }
    fileList:TStringList;

  end;


procedure TMainForm.miImportClick(Sender: TObject);
begin
  AppInfo.ImportDir := BrowseForFolder('ディレクトリ選択','',true);
  if AppInfo.ImportDir <> '' then begin
    self.getImportList(fileList,appInfo.ImportDir);
    self.addNodeforPic;

    ShowMessage(IntToStr(self.fileList.Count));   //ここで8を出力
    self.FThreadImport := TImportFileThread.Create(false);

    self.FThreadImport.Priority := tpLowest;
    self.FThreadImport.OnTerminate := self.importDone;
    self.FThreadImport.FreeOnTerminate := true;
    self.StatusBar.Panels[0].Text := 'Import中です・・・・';
  end;

end;

//対象ディレクトリのjpgファイルを取得
procedure TMainForm.getImportList(var sList: TStringList;dir:String);
var
  rec:TSearchRec;
begin
  self.fileList.Clear;
  
  if  (FindFirst(dir + '\*.jpg', faAnyFile, Rec) = 0) then  begin
    repeat
      
      if  ( (Rec.Name <> '.') and (Rec.Name <> '..') 
      and ((rec.Attr and faDirectory) = 0))
          then fileList.Add(rec.Name);
    
    until (FindNext(Rec) <> 0);

  end;
  
end;

//Import対象のファイル名でtreeNodeを作成しtreeviewに登録する。
procedure TMainForm.addNodeforPic;
var
  i:Integer;
  Node:TTreeNode;
  childNode:TTreeNode;
begin
  Node := self.treeView.Selected;

  repeat

    if Node.Parent <> nil then Node := Node.Parent;
  until (Node.Parent = nil);

  for i := 0 to self.sList.Count - 1 do begin
     childNode := Self.treeView.Items.AddChild(Node.getFirstChild,Self.fileList.Strings[i]);
     childNode.ImageIndex := 3;
  end;
  self.treeView.SaveToFile(AppInfo.workSpaceDir+'app.conf');
end;

procedure TMainForm.importDone(sender: TObject);
begin
  self.StatusBar.Panels[0].Text := 'Import完了';
end;

***************************************************
unit UThreadImport;

interface

uses
  Classes,UAppClass,Windows,Dialogs;

type
  TImportFileThread = class(TThread)
  private
    { Private declarations }
    FSourceDir:TStringList;
    FDistiDir:String;
  protected
    procedure SetDir();
    procedure Execute; override;
  end;

implementation

uses SysUtils,Main;

{ TImportFileThread }

procedure TImportFileThread.Execute;
var
  i:Integer;
begin
  { Place thread code here }
  
  self.Synchronize(self.SetDir);


end;


procedure TImportFileThread.SetDir;
begin
  ShowMessage(MainForm.fileList);   //ここではなぜか0
end;

以上  宜しくお願いします。

編集    削除
ヤマダ  2009-02-11 09:10:04  No: 33304  IP: [192.*.*.*]

お世話になっております。
ヤマダです。

その後も調査し続けた結果どうやらThreadが関係していなことが
わかりました。

ShowMessage(InTToStr(self.sList.count));        //こちらだと8
ShowMessage(InTToStr(MainForm.sList.count));    //こちらだと0

self(:TMainForm)経由とMainForm変数(:TMainForm)経由で
結果が変わっていたみたいです。

何かものすごい勘違いをしているのかもしれません。

いったんこれで解決とさせていただきます。
にしの様、検証までしていただいたのに申し訳ございませんでした。

以上  宜しくお願いいたします。



procedure TMainForm.miImportClick(Sender: TObject);
begin
  AppInfo.ImportDir := BrowseForFolder('ディレクトリ選択','',true);
  if AppInfo.ImportDir <> '' then begin
    self.getImportList(fileList,appInfo.ImportDir);
    self.addNodeforPic;

    ShowMessage(IntToStr(self.fileList.Count));   //ここで8を出力
    ShowMessage(InTToStr(MainForm.sList.count));    //こちらだと0
    self.FThreadImport := TImportFileThread.Create(false);

    self.FThreadImport.Priority := tpLowest;
    self.FThreadImport.OnTerminate := self.importDone;
    self.FThreadImport.FreeOnTerminate := true;
    self.StatusBar.Panels[0].Text := 'Import中です・・・・';
  end;

end;

    ShowMessage(InTToStr(self.sList.count));
    ShowMessage(InTToStr(MainForm.sList.count));

編集    削除
ヤマダ  2009-02-11 09:12:04  No: 33305  IP: [192.*.*.*]

解決!です!

編集    削除