异步过程调用被另一个线程中断
Asynchronous Procedure Call interrupted by another thread?
我刚刚意识到我的APC被另一个线程中断了。所以在这一点上,我想知道这怎么可能。正如我所理解的APC的概念:
- APC不能被正常的用户模式线程中断
- 一旦QueueUserAPC()请求APC,就会立即调度它
- APC具有运行完成语义
这是我最初的情况:我有一个多线程应用程序(1个主线程,1个接收线程)。优先级较低的接收线程正在从外部源接收数据。接收线程也通过使用WaitForSingleObject()
来重新激活。接收到的数据被存储在共享的CCD_ 2中。主线程实际上什么也不做。每隔x毫秒就会发生一个特殊事件,导致接收线程调度APC。这个APC是在主线程的上下文中运行的。
这里有一个关于整个情况的伪源代码示例。
class Example {
public:
Example(void) {
::DuplicatHandle(
::GetCurrentProcess(),
::GetCurrentThread(),
::GetCurrentProcess(),
&m_mainthreadHandle,
THREAD_SET_CONTEXT,
FALSE,
0);
}
void run(void) {
::WaitForSingleObjectEx(m_apcActivation);
}
protected:
private:
void rxThread(void) {
// this seems to be called during the apcRoutine() is running
// as result the shared list m_rxList is corrupted!
::WaitForSingleObject(m_externalActivation);
Data data = externalReceive();
if(data.attribute == SPECIAL) {
::QueueUserAPC(apcRoutine, m_mainthreadHandle, 0);
} else {
m_rxList.push_front(data);
}
}
void apcRoutine(void) {
while(!m_rxList.empty()) {
m_rxList.front().print();
m_rxList.pop_front();
}
}
std::list<Data> m_rxList;
HANDLE m_externalActivation;
HANDLE m_apcActivation;
HANDLE m_mainthreadHandle;
};
void main(void) {
Example e;
e.run();
}
我的问题是:接收线程的WaitForSingleObject()
是否可能中断APC?如果是,为什么?
您似乎对APC有一些误解。
有两种(实际上是三种)APC,usermode和kernelmode(具有两种不同的优先级)APC。
用户模式APC,比如你在代码中使用的APC,其行为与内核模式APC不同。特别是:
- 它们不会抢占线程
- 当您调用
QueueUserAPC
时,它们不会立即运行,除非目标线程已经在可报警等待中被阻塞。相反,APC被排队 - 否则,它们仅在线程进入可报警等待或调用
NtTestAlert
时运行 - 它们并不是不可抢占的,事实上,它们本身并没有什么"特别"之处。它们只是回调,您可以对线程进行排队,并在定义明确的时间进行调用
- 它们不保证运行到完成1,但保证按顺序执行
- 没有办法强制另一个线程执行其排队的APC。目标线程必须使自己能够为其APC的运行发出警报。尽管存在一个未记录的函数
NtAlertThread
,但它并不像人们所期望的那样工作,NtAlertResumeThread
也不工作
另一方面,内核模式APC抢占用户模式线程,并且不可被它们中断(APC_LEVEL APC也不可被PASSIVE_LEVEL APC中断)。
1如果情况也是如此,那将是非常荒谬的。这样,您就可以使用APC完全颠覆调度程序,消耗不确定的CPU时间——无论进程优先级、特权或配额如何。
相关文章:
- 使用 shared_ptr 在中断时结束多线程循环
- 如何使用 SIGINT 在第二个线程中断 getchar
- 可中断线程类 C++11 - 遇到错误?
- 指向成员对象的指针 - 中断线程
- 处理中断时,如何回到主gui线程
- 在 Visual Studio 中的调试中断时设置默认线程,C++
- 返回可中断线程的函数
- 多线程应用程序中的零MQ处理中断
- C++等待用户输入的中断线程
- 如何中断Asynch线程
- 捕获升压线程中断和退出线程的正确方法
- 中断已处于条件变量等待调用中的提升线程
- 中断正在执行MKL或其他第三方函数的线程
- 为什么我不能中断这个特定的提升::线程?
- 《C++并发在行动》中的可中断线程示例
- 使用 Boost::thread 实现可中断线程
- 可以优化中断线程安全
- Windows API中的不可中断线程部分
- 在一定时间后中断线程,在等待时不阻塞
- 为什么此代码被认为是可重复的,以及当操作系统中断线程时究竟会发生什么