Interface ISessionTurn
Whose turn it is to run code in a session: the program that is running, or an event that something outside the workspace raised.
public interface ISessionTurn
Remarks
A session runs one thing at a time. The interpreter is not re-entrant from two threads, and the objects of a program are not safe to be read by one thread while another changes them - but the objects of a library are not the program's to schedule. A host application raises an event when something happens to it, at a time that is its own, on a thread that is its own; the procedures that handle the event are the program's, and run in the program's session.
MS-VBAL says when an event is handled only for the events of the language itself (§5.4.2.20: RaiseEvent invokes the handlers, there and
then), and for the others it says only that DoEvents "yields execution so that the operating system can process externally generated events"
(§6.1.2.8.1.5). The rest is how MS-VBA gets an event from a host application, which is a call from the server to the program, and a program can only take a
call when it is not busy: while it waits for a call of its own to return (the server raises NewWorkbook before Workbooks.Add returns, and the handlers may
answer it), when it yields with DoEvents, and when it is over. That is all of it: nothing is handled in the middle of a statement, and a program that does none of these
is a program no event reaches. Until the session is open to it (IsOpenForEvents) an event waits, and so does whatever raised it.
A program that is running holds the turn, and gives it up while it waits for a call to finish (Yield()), which is what opens the session to the events.
⚖️RDCore provides implementations of this interface licensed under GPLv3.
Properties
EventScope
What surrounds the handling of an event when no program is running to own the session: the host's, since what the handlers print has nowhere to go but where the host says. null when the host says nothing.
Func<IDisposable>? EventScope { get; set; }
Property Value
Remarks
Called when such an event is about to be handled; the scope it returns is disposed when it has been. An event that is handled while a program runs prints where the program does.
IsOpenForEvents
Whether an event that no call was waiting for may be handled now: no program is running, one waits for a call, or one is pumping.
bool IsOpenForEvents { get; }
Property Value
IsRunning
Whether a program runs in the session: what Running last said.
bool IsRunning { get; }
Property Value
Methods
Enter()
Takes the turn for a program that starts. Waits for an event that is being handled to be done.
void Enter()
Exit()
Gives the turn back: the program is over, and the events that waited for it are handled.
void Exit()
Pump()
Lets the asynchronous events that wait be handled, and goes on when they have been: what DoEvents does.
void Pump()
RunEvent(Action)
Runs handle in the session, and returns when it is done.
void RunEvent(Action handle)
Parameters
handleActionWhat handles the event.
Remarks
Called by whatever received the event, on whatever thread that is, once the event may be handled: a synchronous one at once, an asynchronous one when
IsOpenForEvents. It blocks that thread, which is the point: the server that raised the event is waiting for the handlers to be done - they may set an
argument it passed by reference, such as the Cancel of an event that can be cancelled.
Waiting()
Says that an asynchronous event waits for the session to be open to it, for as long as the returned scope is not disposed - which is how Pump() knows there is something to wait for.
IDisposable Waiting()
Returns
Yield()
Gives the turn up while the program waits for a call to finish, and takes it back when the returned scope is disposed.
IDisposable Yield()
Returns
Remarks
A scope for code that is not in a turn does nothing: only what holds the turn can give it up.
Events
Running
Raised with true when a program starts running in the session and none was, and with false when the last one ends: what a
host of windows needs to know to hold their messages while a program runs, as MS-VBA does (none is dispatched until the program waits for it, at DoEvents
or a modal form, or ends). Raised on the thread that starts or ends the program.
event Action<bool>? Running