异步过程调用被另一个线程中断?

Posted

技术标签:

【中文标题】异步过程调用被另一个线程中断?【英文标题】:Asynchronous Procedure Call interrupted by another thread? 【发布时间】:2013-11-22 19:57:17 【问题描述】:

我刚刚意识到我的 APC 被另一个线程中断了。 所以在这一点上,我想知道这怎么可能。 据我了解 APC 的概念:

APC 不能被普通用户模式线程中断 APC 在 QueueUserAPC() 请求后立即调度 APC 具有运行到完成语义

所以这是我最初的情况: 我有一个多线程应用程序(1 个主线程,1 个接收线程)。 较低优先级的接收线程正在从外部源接收数据。 接收线程也通过使用WaitForSingleObject() 重新激活。 接收到的数据存储在共享的std::list 中。 主线程实际上什么都不做。 每 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? 如果是,为什么?

【问题讨论】:

【参考方案1】:

您似乎对 APC 有一些误解。

有两种(实际上是三种)APC,用户模式和内核模式(具有两种不同的优先级)APC。

用户模式 ​​APC(例如您在代码中使用的那些)的行为方式与内核模式 APC 的行为方式不同。特别是:

它们不会抢占线程, 当您调用 QueueUserAPC 时,它们不会立即运行,除非目标线程已在可警报等待中阻塞。相反,APC 被排队。 否则它们仅在线程进入警报等待或调用 NtTestAlert 时运行。 它们并非不可抢占,事实上它们本身并没有什么“特别”之处。它们只是回调,您可以将它们排入线程并在明确定义的时间调用。 它们不保证运行到完成1,但它们保证按顺序执行。 无法强制另一个线程执行其排队的 APC。目标线程必须使其自身处于警报状态,以便其 APC 运行。尽管存在一个未记录的函数NtAlertThread,但它并不能像预期的那样工作,NtAlertResumeThread 也不能。

另一方面,内核模式 APC 会抢占用户模式线程并且不能被它们中断(APC_LEVEL APC 也不能被 PASSIVE_LEVEL APC 中断)。


1 如果是这样的话,那就太荒谬了。这样,您可以使用 APC 完全颠覆调度程序,消耗不确定的 CPU 时间——无论进程优先级、权限或配额如何。

【讨论】:

很遗憾,我只能奖励+1 :(

以上是关于异步过程调用被另一个线程中断?的主要内容,如果未能解决你的问题,请参考以下文章

JAVA多线程

c#中断异步操作

在Windows或Linux等高级系统里,驱动程序是以线程的形式独立运行,还是做为过程被线程调用运行?

线程池中断 任务如何处理

线程中断线程让步线程睡眠线程合并

java线程中断