Link to home
Start Free TrialLog in
Avatar of TicketToTotalitarianism
TicketToTotalitarianism

asked on

[threads] APC?

according to MDSN.
Asynchronous Procedure Calls
An asynchronous procedure call (APC) is a function that executes asynchronously in the context of a particular thread. When an APC is queued to a thread, the system issues a software interrupt. The next time the thread is scheduled, it will run the APC function. APCs made by the system are called "kernel-mode APCs." APCs made by an application are called "user-mode APCs." A thread must be in an alertable state to run a user-mode APC.

When are you making an APC? when a public method of a Tthread-descendant is called from the main thread? (for instance)

Thus if the thread is in a waitstate via SleepEx(1,true), the thread can wake-up when a thread-function is called from the main-thread?
Avatar of TicketToTotalitarianism
TicketToTotalitarianism

ASKER

I guess that when I call a public Thread-function from the main thread, it's executed in the timeslice of the thread? or the other way around? (not apc?)
ASKER CERTIFIED SOLUTION
Avatar of Madshi
Madshi

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
TicketToTotalitarianism:
This old question needs to be finalized -- accept an answer, split points, or get a refund.  For information on your options, please click here-> http:/help/closing.jsp#1 
EXPERTS:
Post your closing recommendations!  No comment means you don't care.
that's too bad ... I needed an APC, to let the thread sleep, and wake-up when needed..

SleepEx

The SleepEx function suspends the current thread until one of the following occurs:
- An I/O completion callback function is called
- An asynchronous procedure call (APC) is queued to the thread.
- The minimum time-out interval elapses
The correct way to do this is to use a signalled event. In Delphi this is a TEvent object. For each Thread class you create put a TEvent object is a member variable. This way every thread can be wakeable.

  TEThread = class(TThread)
  private
    m_Event: TEvent;
    m_Paused: boolean;
  public
    procedure Sleep(Timeout: DWORD);
    procedure WakeUp;
    procedure Pause(pause: boolean);
  protected
    procedure Execute; override;
  published
    property Paused: boolean read m_Paused;
  end;

procedure TEThread.Sleep(Timeout: DWORD);
begin
  m_Event.ResetEvent;
  m_Event.WaitFor(Timeout);
end;

procedure TEThread.WakeUp;
begin
  m_Event.SetEvent;
end;

// BTW. If you want to pause the thread, be wary of using suspend/resume. These functions will stop your thread processing completely whereas you may just want to allow processing to complete but not do any more until unpaused. suspend/resume calls must also be balanced which is tricky if calling them from different threads (inside and out).

procedure TEThread.Pause(pause: boolean);
begin
  if m_Paused <> pause then begin
    m_Paused := pause;
    if not m_Paused then WakeUp; // may as well wake it up.
  end;
end;

procedure TEThread.Execute;
begin
  try
    while not Terminated do begin
      Sleep(..sometime..);
      if not Terminated and not Paused then begin
        .. do stuff ..
      end;
   end;
  except
    // don't allow unhandled exceptions or the thread will GPF - bad if running from, say, a service.
  end;
end;