zoukankan      html  css  js  c++  java
  • APC -- Asynchronous Procedure Call 异步过程调用


    异步过程调用(APC -- Asynchronous Procedure Call )是一种与常用的和简单的同步对象不同的一种同步机制。

    我们在我们线程里使用基本的同步对象如MUTEX去通知其它线程,它应该停下来等我们完成之后你再继续。APCs使用了一种不同的策略,

    因此可能要求应用程序不同的设计。一个APC是一种回调函数类型。与普通的函数指针在调用上有些类似。我们能够在需要通知其它任务一

    些事情时可以调用这样的函数。这个任务将在回调函数内部处理这个事件,而不是等待该事件并在通知后继续工作,实际的工作写在了回调

    函数里。普通回调函数将在调用者上下文中执行该函数。例如,线程A调用回调函数,则回调函数运行在线程A的上下文中,同时线程B也正

    在做一些事情。想一下,一个线程正在重画窗体,而另外一个线程有一些新的信息要显示在窗口上。

    这里的APC机制解决了同步问题,而不需要MUTEX或者Event来包含共享资源。当一个线程使用APC时它告诉系统让其他线程调用该回调函

    数时运行在回调函数自己上下文中。换句话说,任务A告诉任务B去执行一个函数。任务B将不中断它自己的工作区执行这个动作。相反它将

    完成所有的事情,然后去执行该回调函数。这种同步假设了回调函数将在任务完成之后才被调用,所以它已经完成了资源的使用。看一下画

    图的这个例子,它完成了画整个窗体后才开始更新新数据。

    APC的机制将等待目标任务完成它的所有工作。因为今天的应用程序大部分时间是在等待下一个系统事件,它假设当任务完成了所有工作,

    然后进入一个等待状态知道下一系统事件到来。操作系统(同步库)将偷走这个任务的事件等到该任务进入等待状态时,并跳到了回调函数

    的地址上。当函数返回时,该任务将回来在原始的代码或函数上继续等待。

    使用同步机制要求在操作期间不等待,所以我们在处理资源时不需要使用MUTEX或事件。


    APC是一个在特定线程中执行的函数。当一个APC压入APC队列时,系统将引发一个软中断。接下来该线程将被调度,并运行该APC函数。

    APC有2中类型:内核模式的APC和用户模式的APC;内核模式APC由系统产生,而用户模式的由应用程序产生。

    每一个线程都有自己的APC队列。可以使用QueueUserAPC函数把一个APC函数压入APC队列中。APC排队就是请求线程调用APC函数。

    当用户模式的APC压入线程APC队列后,该线程并不直接调用APC函数,除非该线程是处于可通知状态。当一个线程调用SleepEx,

    SignalObjectAndWait、MsgWaitForMultipleObjectsEx,WaitForMultipleObjectsEx或者WaitForSingleObjectEx函数时,它才进入可

    通知状态。如果在APC压入队列之前,线程进入可通知状态,则该APC函数将不被执行,因为此时该线程并不是处于可通知状态。然而,该

    APC函数仍然在队列中,所以在下次调用可通知状态函数时,它将被调用。

    ReadFileEx,SetWaitableTime,SetWaitableTimerEx和WriteFileEx函数是使用一个作为完成通知回调机制的APC来实现的。

    如果你正在使用一个线程池,那么注意该APC并不能和其它信号机制一起工作。因为系统控制了线程池的生命周期,可能在通知之前该线程

    被终止了。应该使用可等待对象比如CreateThreadpoolTimer创建的定时器,而不是基于APC的通知机制--如SetWaitableTimer或

    SetWaitableTimerEx的参数pfnCompletionRoutine。对于I/O,使用一个用CreateThreadpoolIo创建的I/O完成对象或者一个基于事件的

    OVERLAPPED结构体传递到SetThreadpoolWait函数中。

    当一个发起I/O请求时,一个结构体被分配来表示该请求。该结构体称为I/O请求包(IRP -- I/O request packet)。同步I/O,线程将构造

    这个IRP,并发送到设备栈,等待内核完成IRP。异步I/O,线程构造IRP并发送个设备栈。设备栈可能立即完成IRP,也可能返回一个

    pending状态,告诉线程正在处理中。这时,该IRP仍然关联着线程,所以该线程终止时或者调用CancelIo时该IRP将被取消。同时,线程在

    处理设备栈的IRP时能够继续执行其它任务。

    有以下几种方法知道IRP已经完成:
    当IRP完成时将用操作结果更新overlapped结构体,所以线程能够轮询操作是否完成。
    当IRP完成时将触发overlapped结构体中的event时,所以当操作完成时,线程能同步并处理。
    把IRP压入线程未决的APC时,当线程处于可通知状态时将执行APC函数并返回等待操作带有指示它执行一个或多个APC函数的状态。
    把IRP压入一个I/O完成端口时,它将被等待该完成端口的下一个线程执行。

    等待IO完成端口的线程并不等待可通知状态。因此,如果这些线程发起了被作为APC设置为完成的IRP到线程时,这些IPC完成不能及时地发

    生;它们将在线程从IO完成端口获得请求并碰巧进入了可通知状态时才发生。


    http://asyncop.com/link.aspx?apc
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms681951%28v=vs.85%29.aspx

  • 相关阅读:
    Android 编程下 Eclipse 恢复被删除的文件
    Android 编程下背景图片适配工具类
    Android 编程下 Managing Your App's Memory
    Android 编程下代码之(QQ消息列表滑动删除)
    Android 编程下 Canvas and Drawables
    Android 编程下 AlarmManager
    Android 编程下去除 ListView 上下边界蓝色或黄色阴影
    Java 编程下字符串的 16 位、32位 MD5 加密
    C#枚举类型和int类型相互转换
    MVC和普通三层架构的区别
  • 原文地址:https://www.cnblogs.com/C-Sharp2/p/APC.html
Copyright © 2011-2022 走看看