在C ++,Windows平台中,我想以原子的形式执行一组函数调用,以便执行不会切换到我的进程中的其他线程。我该怎么做呢?任何想法,提示?
编辑:我有一段代码:
someObject->Restart();
WaitForSingleObject(handle, INFINITE);
现在 Restart()函数异步工作,所以它会快速返回,当someObject重新启动时,它会从另一个线程向我发送一个事件,在那里我发信号通知事件句柄我就是等待,从而继续处理。但现在的问题是,在代码到达 WaitForSingleObject()部分之前,我收到重启完成事件并发出事件信号,之后 WaitForSingleObject()永远不会返回没有再发出信号。这就是为什么我要将 Restart()和 WaitForSingleObject()作为原子执行。
答案 0 :(得分:9)
这通常是不可能的。您无法强制操作系统切换到其他线程 您可以做的是以下之一:
InterlockedIncrement()
和InterlockedCompareExchange()
答案 1 :(得分:7)
您不希望所有线程都等待,您只想等待新线程完成,而不存在丢失信号的风险。这可以使用信号量来完成。
使用CreateSemaphore(NULL,0,1,NULL)创建此代码和最终由Restart执行的代码已知的信号量。 在你展示的代码中,你仍然会使用WaitforSingleObject来等待你的信号量。当执行Release代码的线程完成它的工作时,让它调用ReleaseSemaphore。
如果首先调用ReleaseSemaphore,WaitforSingleObject将允许您立即传递。如果首先调用WaitforSingleObject,它将等待ReleaseSemaphore。
MSDN也应该帮助你。
答案 2 :(得分:2)
丢失事件竞赛的一般解决方案是计数信号量。
答案 3 :(得分:1)
您是否使用PulseEvent()
发出信号?如果是这样,那就是问题。
根据MSDN,
如果没有线程在等待,或者没有 线程可以立即释放, PulseEvent只是设置事件 对象的状态为无信号和 回报。
因此,如果在等待之前发出手柄信号,则手柄会立即被PulseEvent()
置于无信号状态。这似乎是你“失踪”事件的原因。要更正此问题,请将PulseEvent()
替换为SetEvent()
。
但是,在这种情况下,您可能需要在等待完成后重置事件。这当然取决于在应用程序的生命周期内是否多次执行此代码。假设您的等待线程是等待句柄的 仅 线程,请使用CreateEvent()
创建自动重置事件。这将在您等待线程释放后自动重置句柄,使其在下一次自动可用。
答案 4 :(得分:0)
好吧,你可以暂停(使用SuspendThread)流程中的所有其他线程,但我想你应该重新考虑你的程序设计。
答案 5 :(得分:0)
这很容易解决。只需确保事件是自动重置事件(请参阅CreateEvent的参数)并仅将SetEvent调用到事件句柄,从不调用ResetEvent或PulseEvent或其他一些事情。所以WaitForSingleObject将始终正确返回。如果事件已经设置,WaitForSingleObject将立即返回并重置事件。
答案 6 :(得分:-1)
虽然我一般都担心你的设计(即你正在使并发任务顺序完成,从而失去了努力使其并发的所有好处),但我认为我看到了简单的解决方案。
将事件句柄更改为MANUAL RESET而不是AUTORESET。 (参见CreateEvent)。
然后你不会错过这个信号。 在WaitForSingleObject(...)之后,调用ResetEvent()。
编辑: 忘了我刚说的话。那不行。见下面的评论。