Cancelling events |
Top Previous Next |
The WhiskerServer sends an Event: message to the control whenever an event occurs of which the client has requested notification with one of the 'SetEvent' commands. Usually, this event is then simply passed on, along with the event's time stamp (the time, in ms, from the client's connection or the last call to ResetClock), to the _Event() subroutine of the control.
However, there are two occasions when such an event is not simply passed on:
Consider the following extract from a VB program:
Private Sub Start() Whisker.TimerSetEvent "TrialOver", 1000, 0 Whisker.LineSetEvent "Lever", "LeverPress", wsLineToOn End Sub
Private Sub Whisker_Event(ByVal Message As String, ByVal Time As Long) Select Case Message Case "TrialOver" Whisker.LineClearEvent "LeverPress" Call ITI Case "LeverPress" Whisker.TimerClearEvent "TrialOver" Call give_reinforcer Call ITI End Select End Sub
This code seems clear enough, I hope. Whatever the event that occurs first, the client cancels other outstanding events, and moves to the ITI (giving a reinforcer if the rat had pressed) . No problems, it seems.
But what if the TrialOver timer finishes just before the rat presses a lever?
The following sequence might happen:
Thus, because it takes some time for the client's message to reach the Server, there is always the possibility that two events that seem 'mutually exclusive' may actually both be generated – and the ITI routine gets called twice. This could have all sorts of nasty consequences – possibly trying to run two trials at the same time!
This may be a rare event, as the messages pass so quickly, but that doesn't mean we can ignore the problem – and with devices that may generate lots of events quickly (like a touchscreen) it could happen frequently!
In general: ClearEvent commands cannot block events that are 'on the way' from the Server.
This may be inconvenient for some clients, especially for those people who are used to languages such as !Arachnid. Whisker SDK therefore adds an extra command to make this situation easy to avoid.
Instead of (or as well as) telling the Server to 'not send any more Events', we can instruct the SDK to ignore any future events of a certain name (Note: we cannot kill just 'line events' of this name – the event name is all the client will receive!).
The SDK command
Whisker.KillEvent <eventname>
tells the SDK to ignore any events (i.e. not to call the _Event subroutine) with the name eventname. This can be used to make sure that we do not respond to events in the kind of situation shown above. The effect of KillEvent can be reversed by
Whisker.ReviveEvent <eventname>
or
Whisker.ReviveEvent ""
to undo all previous KillEvent commands (and respond as normal to all events).
So if we replace 'ClearLineEvent' with 'KillEvent', we have solved the problem:
Note that, in this case, the server will continue to send LeverPress messages, until we Call ClearEvent. So we can just ReviveEvent on the next trial when we care about them again.
In summary:
SetEvent and ClearEvent are used to control whether the Server sends a message. You cannot be certain that an event is not 'on the way' when you clear it.
KillEvent and ReviveEvent are used to control whether or not the SDK calls your _Event() procedure when the event arrives. You can be certain that an Event will not be responded to after it has been Killed.
|