Subsequent events not triggering in while loop - events

I have a MAIN VI and a SUB VI which communicate events through control refnum. flow of events is as follows.
1) sub vi changes a value of its control and this event is handled in the main vi(this works).
2) main vi in response to the event changes one of its control and triggers an event from the event handler itself which is handled in the subvi event handler.(this also works).
The first phase is over. Now the main vi is running a while loop and the sub vi is running a while loop and main vi triggers an event every ~150ms. Which is to be handled in the subvi. This is the part which is not happening. I can see the main vi's control getting updated but the event(if generated) is not handled by the subvi. I'm using control's property node->Value(signalling) to change the value as well as trigger the event. What can be the possible cause?
note: the control (whose value is changed), event handler are the same as in the first phase.
Hope my question is clear.

i found the problem .
the subsequent events were not being handled because the loop in which the event handler ran looped once
i.e the initial condition was itself false so the loop only ran once.
this loop was controlled by stop if true. it had to be continue if true.
the boolean variable that controlled this loop was true. this should have been my first clue.

Related

How to trigger the event in AnyLogic and then make it cyclic?

I would like to make the cyclic event. This event periodically calculates some parameters of the model. However, the event should be triggered once by a condition. I have no idea how to do that.
I tried to make the event.reset() at the beginning and then restart it after the appropriate condition is met.
However, I received the errors:" agent cannot be resolved to a variable"
If I delete the reset and restart functions for the event, everything will be ok. The event is cyclic and works fine.
The double click on the error shows the stings where the error is occurred (highlighted with red color):
On model start-up, suspend the event by using:
event.reset();
Once the condition you have is met, use:
event.restart();

Programmatically fire button click event

Is there a way to fire a button click event programmatically in Clarion? I've tried the following but they haven't worked:
! Doesn't work:
?ResetInput
! Also doesn't work:
?ResetInput:Accepted
I figured out a solution after a few hours of searching:
POST(EVENT:Accepted, ?ResetInput)
Please post any other answer if there's a more correct way of doing this.
Here's the info regarding the POST function from the Clarion help docs:
POST( event [,control] [,thread] [,position] )
event: An integer constant, variable, expression, or EQUATE containing an event number. A value in the range 400h to 0FFFh is a User-defined event.
control: An integer constant, EQUATE, variable, or expression containing the field number of the control affected by the event. If omitted, the event is field-independent.
thread: An integer constant, EQUATE, variable, or expression containing the execution thread number whose ACCEPT loop is to process the event. If omitted, the event is posted to the current thread.
position: An integer constant, EQUATE, variable, or expression containing either zero (0) or one (1). If one (1), the event message is placed at the front of the event message queue. If omitted or zero (0), the event message is placed at the end of the event message queue.
POST posts an event to the currently active ACCEPT loop of the specified thread. This may be a User-defined event, or any other event. User-defined event numbers can be defined as any integer between 400h and 0FFFh. Any event posted with a control specified is a field-specific event, while those without are field-independent events.
POSTing an event causes the ACCEPT loop to fire but does not cause the event to "happen." For example, POST(EVENT:Selected,?MyControl) executes any code in EVENT:Selected for ?MyControl but does not cause ?MyControl to gain focus.
Example:
Win1 WINDOW('Tools'),AT(156,46,32,28),TOOLBOX
BUTTON('Date'),AT(0,0,,),USE(?Button1)
BUTTON('Time'),AT(0,14,,),USE(?Button2)
END
CODE
OPEN(Win1)
ACCEPT
! Detect user-defined event:
IF EVENT() = EVENT:User THEN BREAK END
CASE ACCEPTED()
OF ?Button1
POST(EVENT:User,,UseToolsThread) !Post field-independent event to other thread
OF ?Button2
POST(EVENT:User) ! Post field-independent event to this thread
END
END
CLOSE(Win1)

Why does SetWinEventHook sometimes stop/pause monitoring events?

Starting up a WinEventHook doesn't seem to be working reliably.
What would cause an event hook to only monitor events (or run the identified event proc function) sometimes?
ie. inside an IE8 BHO
HWINEVENTHOOK eHook = ::SetWinEventHook(EVENT_OBJECT_SHOW, EVENT_OBJECT_REORDER
, 0
, MSAALib_WinEventProc
, GetCurrentProcessId(), GetCurrentThreadId()
, WINEVENT_OUTOFCONTEXT );
I've been getting events quite regularly, but after a recent build it doesn't work except when I'm also running MS "Accessible event watcher", stopping and starting the event watcher also stops and starts my event proc being called.
I haven't changed the SetWinEventHook in any recent build so I do not believe this is the cause.
All the other thread/message pumping actions are taking place as expected so I do not believe failure to pump messages on the thread is the cause.
Testing getting reorder events using http://www.quirksmode.org/dom/events/tests/DOMtree.html and adding/removing test elements.
Edit:
Upon further testing it appears the change may have been that I stopped running the "Accessible event watcher" and not the build.
The range of events captured by the event hook without the "Accessible event watcher" appears to be [first, last) or eventMin to eventMax-1 which is not as per the doc SetWinEventHook when starting the "Accessible event watcher" the range changes and appears to be [first,last] so using an eventMax of EVENT_OBJECT_FOCUS seems to get the desired result of seeing EVENT_OBJECT_REORDER.
Is there something I'm missing here, or is the doc just wrong and the event watcher is doing something aswell?

What does "DoEvents" do in vb6?

What does "DoEvents" do in vb6 ?
Why do I get the error message "Out of stack space" ? What does it mean ?
DoEvents() allows other Windows messages to be processed.
The reason you get an out of stack space error is probably because DoEvents() is allowing events to occur that call your code again, which again calls DoEvents(), and so on until the stack space, which tracks the return addresses for all these calls, has run out.
In general, I do not recommend using DoEvents() due to problems like these and the fact that it violates the overall event-driven design of Windows.
A slightly different way of looking at DoEvents is that it flushes the events in the event queue. If your sub or function triggers an event, that event handler becomes a sub that is in line to run as soon as your sub/function is finished. DoEvents says to run that event handler sub now, instead of waiting till the end of your sub.
While I agree in spirit with Jonathon about not using DoEvents, I would temper his statement by saying I only recommend using it if you know exactly why, and know all of the repercussions of changing the order of the event queue this way. Most often, DoEvents is indicated when you want to update your screen in some way from within the context of a subroutine, before the subroutine is finished executing.
An example of this is when you are using the ProgressBar control. Suppose you are iterating through several thousand records, and want to provide feedback to the user as to how far along you are by updating a progress bar. You might interrupt your loop every hundred records and change the value on the progressbar control. However (unless you do something about it) you won't see the change on the screen until after the progressbar's change event handler runs, and that handler won't run until your sub is done executing. It will just get put in the event queue. The way to force the change event to run immediately, suspending your sub, is to call DoEvents. This will flush all existing events from the queue--in this case your progressbar's change event--and will update the progressbar control on the screen.
Now, "out of stack space" basically means that you've been caught in an endless loop of function calls. The most basic way to cause that is this:
Public sub MySub()
MySub
End Sub
And then call MySub from somewhere. You'll get an out of stack space error. If you look at the Call Stack, you'll see a very long line of calls to MySub.
A well-known real-world example of this would happen in older versions of VB:
Public Sub TextBoxArray_LostFocus(index as Integer)
If TextBoxArray(index) = "" Then
TextBoxArray(index).SetFocus
MsgBox "Please enter a value"
End If
End Sub
This situation assumes two members of a TextBox control array called TextBoxArray. Now, if the user starts with the first one (index 0) and moves to the second one (index 1) then index 0's LostFocus event will fire. However, VB would also internally set the focus to the index 1 box. Then the code would set the focus back to index 0, firing index 1's LostFocus event! You're caught in a loop. They fixed that in VB5 or 6 by waiting to set the focus until the LostFocus event was done executing.
I would clarify Johnathon's answer in that it pumps that VB message loop and allows the VB Runtime to process windows messages, which is the opposite of Sleep which allows for Windows to process its events (not necessary in the world of Multicore CPUs and true multitasking OS's but when VB6 was written Windows 9x was the dominant OS and a hard loop that only had DoEvents in it would spike the CPU usage to 100%). So seeing things like
While fDoneFile = False
DoEvents
Sleep 55
Wend
was a common pattern throughout the VB6 world.
As stated else where, DoEvents allows other events in your application to fire. Here's an example of how you can use DoEvents without the "Out of stack space" issue. This makes sure you don't run through the code multiple times by using a Boolean to indicate the code is running.
Sub Example()
'Create static variable to indicate the sub is running.
Static isRunning As Boolean
'Exit the sub if isRunning
If isRunning Then Exit Sub
'Indicate sub is running
isRunning = True
'Sub does stuff
DoEvents
'Ends up calling sub again
Example 'Added just to prove via testing.
'Indicate sub is no longer runningrunning
isRunning = False
End Sub

Modal operation using IMessageFilter and DoEvents

This is a Windows Forms application. I have a function which captures some mouse events modally till a condition is met. For example, I would like to wait for the user to select a point in the window's client area (or optionally cancel the operation using the Escape key) before the function returns. I am using the following structure:
Application::AddMessageFilter(someFilter);
while(someFilter->HasUserSelectedAPoint_Or_HitEscapeKey()){
Application::DoEvents();
}
Application::RemoveMessageFilter(someFilter);
This works quite nicely except for taking up nearly 100% CPU usage when control enters the while loop. I am looking for an alternative similar to what is shown below:
Application::AddMessageFilter(someFilter);
while(someFilter->HasUserSelectedAPoint_Or_HitEscapeKey()){
// Assuming that ManagedGetMessage() below is a blocking
// call which yields control to the OS
if(ManagedGetMessage())
Application::DoEvents();
}
Application::RemoveMessageFilter(someFilter);
What is the right way to use IMessageFilter and DoEvents? How do I surrender control to the OS till a message is received? Any GetMessage equivalent in the managed world?
You could sleep the thread for 500ms or so between DoEvents() calls. Experiment with different values to see what feels right.

Resources