1

複数のスレッド/プロセスから「listMessages」と呼ばれる TListBox に書き込みたいのですが、これを行うには次の 2 つの手順があります。

1- オブジェクトを追加する場合:

procedure Log(Msg: String; Color: TColor);
begin
  listMessages.Items.AddObject(Msg, Pointer(Color));
  listMessages.ItemIndex := listMessages.Items.Count -1;
end;

2- TIdCriticalSection と呼ばれるprotectListMessagesを使用:

procedure TMainForm.safelyLogMessage(mess : String);
begin
  protectlistMessages.Enter;
  try
    listMessages.Items.Add(mess);
    listMessages.ItemIndex := listMessages.Items.Count -1;
  finally
    protectListMessages.Leave;
  end;
end; 

どちらが最適か (高速 + スレッド セーフ) を教えてください。または、スレッド/プロセスから TListBox にメッセージを書き込む 3 番目の方法を教えてください。

4

1 に答える 1

4

あなたの選択肢はどれも良くありません。オプション 3 を使用する必要があります。

ポイントは、UI コントロールへのアクセスはすべてメイン スレッドで実行する必要があるということです。TThread.Synchronizeまたはを使用TThread.Queueして、UI コードをメイン UI スレッドにマーシャリングします。これを行うと、UI スレッドでコードを実行するという行為自体がコードをシリアル化するため、コードをさらにシリアル化する必要はありません。

コードは次のようになります。

procedure TMainForm.Log(const Msg: string; const Color: TColor);
var
  Proc: TThreadProcedure;
begin
  Proc :=
    procedure
    begin
      ListBox1.AddItem(Msg, Pointer(Color));
      ListBox1.ItemIndex := ListBox1.Count-1;
    end;

  if GetCurrentThreadId = MainThreadID then
    Proc()
  else
    TThread.Queue(nil, Proc);
end;

あなたの更新では、別のプロセスからリストボックスに書き込む必要があると述べています。これは、問題のコードでは達成できません。そのためには、プロセス間通信 (IPC) が必要です。Windows メッセージを送信するのが合理的な方法ですが、他の IPC オプションも利用できます。しかし、プロセスという用語を使用するとき、あなたは誤解していると思います。あなたはプロセスを意味しているのではないのではないかと思いますが、あなたが何を意味しているのか、私にはわかりません.

于 2014-07-03T11:14:40.607 に答える