2012-03-02 25 views
5

我正在处理这种类型的动作队列线程,我想等待某个动作被执行。我想在主线程中创建动作,然后将其传递给队列线程函数(到队列末尾)并等待执行此动作。所以我需要区分我刚才查询的行为已经执行并等待它。将事件从主线程传递给工作线程并等待它是否安全?

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

  • 是否与Windows事件对象的线程安全的工作?
  • 如果是的话,这个概念会有效吗?

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; 

谢谢!

+0

在按钮事件处理程序中等待事件将阻止主线程,所以这不是你想要的!也许你可以使用事件代替(线程完成时调用) – jpfollenius 2012-03-02 15:43:57

+2

这样的等待不会做你想做的事。它不能被打断。你为什么要阻止10秒?这很奇怪。 – 2012-03-02 15:50:21

+0

理想无限;这是重命名行动。我需要进入VirtualTreeView节点的编辑模式并保持编辑器处于活动状态,直到从线程获得重命名操作的结果(我有一个额外的事件处理程序,如果重命名成功并且我退出时需要传递结果这个事件处理程序编辑器被隐藏)。 – 2012-03-02 16:02:29

回答

4

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

+1

不一定。我认为句柄可能是线程特定的,或者至少不是线程安全的。如果另一个线程想要访问同一个事件,可能需要调用DuplicateHandle,或者需要使用相同的事件名称来调用CreateEvent本身。 – 2012-03-02 16:24:11

+0

经验上,句柄可以用于其他线程 - 我经常以这种方式使用事件。 – 2012-03-02 17:48:25

+0

@RobKennedy这正是我一直在做的事情,直到今天,当我看到一个例子,有人刚刚有两个线程使用相同的句柄变量... – 2015-04-01 23:08:54

3

不要等待GUI事件处理程序中的线程。不要等待事件,信号量或互斥量,sleep()循环,DoEvents循环或其任何组合。

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

+0

当与主花纹沟通时使用'PostMessage'的替代方法是1)'Thread .Queue'如此处所述[synchronize-and-queue-with-parameters](http://www.uweraabe.de/Blog/2011/01/30/synchronize-and-queue-with-parameters/#more-135 )(这对于FireMonkey应用程序非常有用),或者2)使用“线程安全队列”并使用定时器循环从主线程轮询队列。 – 2012-03-03 13:05:26

+0

'synchronize-and-queue-with-parameters'是OK-ish,但是它会进行两次系统调用,以找出它正在运行的线程:(使用定时轮询定时器可以周期性地显示最新的线程,日期值是很多变量的值,但是如果用于轮询队列则会引入延迟。 – 2012-03-03 14:50:47

相关问题