0

私を手伝ってくれますか。私はコンポーネント (TListView のようなもの) を作成しています。私のコンポーネントでは、3 つの手順を 1 つずつ実行します。

procedure findFiles(Path:String); // using FindFirst, FindNext
procedure ArrangeItems; // assigns Item Position
procedure SetIcons;    // Loads Images, resizes, adds to ImageList

コンポーネントにスレッドを使用してこれらすべての手順を実行させる方法がわかりません。少なくとも最初の手順 (findFiles) は理解できません。さまざまな方法を試しましたが、何も出てきません。

ここに私が持っているもののスケッチがあります(単なる基本的な例です)。

 type
  TSearchThread = class(TThread)
  private
    SIView: TSIView;
  protected
    procedure Execute; override;
    procedure DoSearch;
  public
    constructor Create(fSIView: TSIView);
  end;



 constructor TSearchThread.Create(fSIView: TSIView);
 begin
  SIView := fSIView;
  FreeOnTerminate := True;
  inherited Create(False);
  Priority := tpLower;
 end;

 procedure TSearchThread.Execute;
 begin
  inherited;
  Synchronize(DoSearch);
 end; 

 first I tried to perform 
   SIView.findFiles('C:\');
   ArrangeItems;

そして、スレッドを実行して適切なアイコン (SetIcons) を設定します。

 procedure TSearchThread.DoSearch;
 begin
  SetIcons;
 end;

それは機能しましたが、バグがありました。コンポーネントがすべてのアイテムのアイコンを作成するわけではない場合があり、一部のアイテムのアイコンが完全に黒色で塗りつぶされている場合もあれば、アイコンがまったくない場合もあります。

次に、スレッドで 3 つの手順をすべて実行することにしました。

 procedure TSearchThread.DoSearch;
 begin
  SIView.findFiles('C:\');
  ArrangeItems;
  SetIcons;
 end; 

その結果、アイコンの作成で同じバグが発生し、指定されたフォルダーを検索する代わりに、アプリケーションがあったフォルダーを検索しました。

あなたが私をもっと理解するために、私は複数のタブを持つファイルマネージャを作成しようとしています.

私のコードを整理する方法を理解するのを手伝ってくれませんか?!!!! スレッディングに関するドキュメントはあまりないので、例を挙げることができるかもしれません。


また会ったね。
AsyncCalls と OmniThreadLibrary の両方を試しました。どちらも「バックグラウンド」ファイル検索の例を持っていました。最初に、AsyncCalls は本当にうまく機能したので、私のアプリケーションにより適していることがわかりました。私は AsyncCalls を使用して 3 つの手順を実行しましたが、それこそが私が探していたものでした。また、OmniThreadLibrary を使用してプロシージャを呼び出してみましたが、スレッドで実行されていないように見えました。それが私が AsyncCalls を好んだ理由ですが、質問があります。実行中の IAsyncCall を停止するにはどうすればよいですか? たとえば、アプリケーションがマルチタブである前に述べたように、ユーザーが 3 つのタブを開き、各タブでファイル検索を実行した場合、2 番目のタブでファイル検索を停止するにはどうすればよいでしょうか?

私が何をしたいのかをより明確にするために、ここにスケッチがあります:

フォームには 3 つの TMemo と 3 つの TButton があります

var 
 a1, a2, a3: IAsyncCall;


procedure TForm1.Search(Path:String; MEMO:TMemo);
begin
 /////// Finds files and adds to MEMO 
end;

3 つのボタンはすべて、異なる TMemo (Memo1、Memo2、Memo3) を指していることを除いて、同じことを行います。

procedure TForm1.Button1Click(Sender: TObject);

 procedure DoSearch;
 begin
  Search('C:\', Memo1);     
 end;

begin
  a1 := LocalAsyncCall(@DoSearch);

  while AsyncMultiSync([a1], True, 0) = WAIT_TIMEOUT do
      Application.ProcessMessages;
end;

したがって、3 つのボタンすべてをクリックすると、3 つの IAsyncCall が実行されます。まだ実行中にそれらのいずれかを停止するにはどうすればよいですか?

4

2 に答える 2

7

このようなコードで

 procedure TSearchThread.Execute;
 begin
  inherited;
  Synchronize(DoSearch);
 end; 

ワーカースレッドはまったく使用しません。すべての作業は、Synchronize呼び出しを介してメインスレッドで実行されます。これは、スレッドを使用してはならない方法の例です。つまり、実行コードは次のようになります。

 procedure TSearchThread.Execute;
 begin
   if FindFirst(..) then begin
     repeat
       Queue(..); // inform the main thread about the item is found
     until not FindNext(..)
     FindClose;
   end;
   Queue(..); // inform the main thread that the work is completed
              //   and we are about to terminate
 end; 
于 2010-10-24T01:19:13.807 に答える
5

あなたの最良の選択肢はAsyncCallsライブラリを使用することだと思います。これは非常に使いやすく、ウェブページにはあなたの例に非常によく似たデモが含まれています。

于 2010-10-23T23:45:51.640 に答える