Multithreading 将事件从主线程传递到工作线程并等待它是否安全?

Multithreading 将事件从主线程传递到工作线程并等待它是否安全?,multithreading,delphi,events,thread-safety,delphi-xe2,Multithreading,Delphi,Events,Thread Safety,Delphi Xe2,我正在处理这样一个操作队列线程,我想等待执行某个操作。我想在主线程中创建操作,然后将其传递给队列线程函数(到队列的末尾),并等待执行此操作。因此,我需要区分刚才查询的操作是否已执行并等待它 我有以下(伪)代码,我想知道 它是否使用Windows事件对象线程安全 如果是,这个概念是否有效 谢谢 是的,那很好。所有线程都可以自由使用CreateEvent返回的句柄。由于这是它的主要用途,任何其他东西都会使它变得毫无用处:)不要在GUI事件处理程序中等待线程。不要通过等待事件、信号量或互斥体、s

我正在处理这样一个操作队列线程,我想等待执行某个操作。我想在主线程中创建操作,然后将其传递给队列线程函数(到队列的末尾),并等待执行此操作。因此,我需要区分刚才查询的操作是否已执行并等待它

我有以下(伪)代码,我想知道

  • 它是否使用Windows事件对象线程安全
  • 如果是,这个概念是否有效


谢谢

是的,那很好。所有线程都可以自由使用CreateEvent返回的句柄。由于这是它的主要用途,任何其他东西都会使它变得毫无用处:)

不要在GUI事件处理程序中等待线程。不要通过等待事件、信号量或互斥体、sleep()循环、DoEvents循环或其任何组合来实现


如果您想与主线程通信以表明线程池中已处理了某些内容,请查看PostMessage()API

在按钮事件处理程序中等待事件将阻止主线程,因此这不是您想要的!也许您可以使用一个事件来代替等待(每当线程完成时调用该事件),因为等待不会执行您想要的操作。它不能被打断。你为什么要封锁10秒?这很奇怪,理想情况下是无限的;它是用来重命名动作的。我需要进入VirtualTreeView节点的编辑模式,并保持编辑器处于活动状态,直到我从线程获得重命名操作的结果(我有一个额外的事件处理程序,如果重命名成功,我需要在其中传递结果,当我退出此事件处理程序时,编辑器将隐藏)。谢谢@David。现在我看到它阻止了所有的消息处理,从而阻止了整个主线程(表单)。在我看来,句柄可能是线程特定的,或者至少不是固有的线程安全的。如果另一个线程想要访问同一事件,可能需要调用DuplicateHandle,或者需要使用相同的事件名称调用CreateEvent本身,句柄可以从其他线程使用-我经常以这种方式使用事件。@RobKennedy这正是我一直在做的事情,直到今天,当我看到一个例子,有人刚刚让两个线程使用相同的句柄变量…在与主线程通信时使用
PostMessage
的替代方法是1)
Thread.Queue
如本文所述(这对FireMonkey应用程序很有用)或2)使用
线程安全队列
并使用计时器循环从主线程轮询队列。“synchronize-and-Queue-with-parameters”是可以的,但它会进行两次系统调用以确定它在哪个线程上运行:(使用计时器轮询可以定期显示许多变量的最新值,但如果用于轮询队列,则只会引入延迟。
type
  TMyThread = class(TThread);
  private
    FEvent: THandle;
  protected
    procedure Execute; override;
  public
    procedure DoSomething(const AEvent: THandle);
  end;

procedure TMyThread.Execute;
begin
  //  is it working with events thread safe ?
  SetEvent(FEvent);
  //  the thread will continue, so I can't use WaitFor
  //  but it won't set this specific FEvent handle again
  //  I'm working on such kind of an action queue, so once the action with ID,
  //  here represented by the FEvent will be processed, it's removed from 
  //  the action queue
end;

procedure TMyThread.DoSomething(const AEvent: THandle);
begin
  FEvent := AEvent;
end;

//  here's roughly what I want to do

procedure TForm1.Button1Click(Sender: TObject);
var
  OnceUsedEvent: THandle;
begin
  //  the thread is already running and it's instantiated in MyThread
  //  here I'm creating the event for the single request I need to be performed
  //  by the worker thread
  OnceUsedEvent := CreateEvent(nil, True, False, nil);
  try 
  //  here I'm passing the event handle to the worker thread (like a kind of
  //  a request ID)
    MyThread.DoSomething(OnceUsedEvent);
  //  and here I want to wait for 10 seconds (and also interrupt this waiting 
  //  when the user closes the application if possible ?) for the thread if
  //  performs my request
    WaitForSingleObject(OnceUsedEvent, 10000);
  finally
  //  close the event handle
    CloseHandle(OnceUsedEvent);
  end;
  //  and continue with something else
end;