double user event?!

Workarounds and usability notes.

double user event?!

Postby John Robin Dove » Thu Aug 13, 2015 2:27 pm

I have a new problem. A non-periodic timer is set in an object. When the object receives the user event it increments a global variable. The problem is it appears to receive a user event twice! So it it increments the variable twice causing havoc!
John Robin Dove
 
Posts: 486
Joined: Thu Jan 23, 2014 4:35 am

Re: double user event?!

Postby Clifton » Thu Aug 13, 2015 5:08 pm

This is a fairly easy situation to run into.

Whether a user event gets sent multiple times has everything to do with how user events are generated in your application.
If you are using the Action Editor send user event action and the target object is inside a group, then the event may be triggered multiple times.

If you are using pgTBObjSet() to send user events, then you will have a lot more control over what happens and which objects are specifically targeted. We have extensively tested pgTBObjSet() against the scenario of multiple event firing and making sure only targeted objects receive the events. If several remote objects are firing user events using pgTBObjSet(), then make sure to set preventMultiDelay = true. This will force all previous events on the targeted object to be terminated and yield processing only for the most recent event. However, for preventMultiDelay = true to have any effect, you will have to set the delay parameter to a value greater than zero. Otherwise, there will no queued delays to terminate.

Not knowing how you are generating the events makes this a difficult situation troubleshoot. However, what is stated above may help you to determnine how the events are bubbling in your application. By default, pgTBObjSet() permits multiple event firing unless preventMultiDelay is set to true.

Of course there are other ways to generate multiple user events. For example, action code that is not thought-through fully could inadvertently be doing this as well. You can debug the source of each user event by setting the value parameter to some value that identifies its source. That way you can identify which object is guilty of multiple triggers or whether code on several objects is exhibiting the same behavior.

    Debug recommendation:
    If you are using pgTBObjSet() to send the user event, then set myValue to the name of the object sending the event. You can do something similar with the Actions Editor send user event action by setting the value to send to the name of the object sending the event. Then use a simple prompt action on the object receiving the event to check the contents of the value parameter each time the user event fires. This will reveal the object sending the event and will help in diagnosing the problem.

    My guess is that you will find that the Actions Editor send user event action is generating the multiple events. Later ToolBook versions improved on this somewhat, but they still demonstrated the multiple event issue—that is, unless the receiving object filtered the event via the value parameter. In the majority of cases, the problem is solved by using PowerPac's pgTBObjSet() to manage events.
Clifton
Site Admin
 
Posts: 732
Joined: Tue Jan 14, 2014 1:04 am

Re: double user event?!

Postby John Robin Dove » Fri Aug 14, 2015 5:03 am

Hi Clifton,

Thanks for the detailed help. I probably didn't explain clearly enough. I am using pcTimer to pause video playback for a number of seconds set by the user. When the time is up my global variable currentTrigger is incremented so that the next action programmed by the user can be carried out at the appropriate time. While the video is playing a set of triggers (textlines containing items in an array) is scanned so that user-programmed actions can be performed.

In this case trigger 1 causes a text to be displayed without pausing playback and trigger 2 pauses playback (for example because the teacher has decided that the text is too long to be understood without including a pause). After the actions required by each trigger have been carried out currentTrigger is set to currentTrigger + 1 so after 2 it should be 3. The problem is it goes from 2 to 4 because 2 user events are received instead of 1.

The sequence is as follows: trigger 2 activates object method pauseForText, the last line of which is pcTimer("", itemValue, "ML1", ""), itemValue = 5000, field "ML1" restarts the video and increments currentTrigger by 1. Unfortunately it does this twice and I can't understand why. The object method pauseForText definitely only executes pcTimer once so where is the second user event coming from? The value for each user event is the same "ML1", 5, 5000.

I could use a global variable to "cure" this but it seems unnecessarily complicated and I already have more global variables than I would like.

Here's a picture of the action sequence for field "ML1"

Image
Last edited by John Robin Dove on Fri Aug 14, 2015 5:45 am, edited 1 time in total.
John Robin Dove
 
Posts: 486
Joined: Thu Jan 23, 2014 4:35 am

Re: double user event?!

Postby Clifton » Fri Aug 14, 2015 5:15 am

UPDATED:

After reading this again, you may want to check whether the video container field is getting a user event when the video is paused by the pgTimer() user event. That couild be where the collision is occurring. If that is the case, use htmlVideoControl() to check the video status "isPaused" before processing actions.
Clifton
Site Admin
 
Posts: 732
Joined: Tue Jan 14, 2014 1:04 am

Re: double user event?!

Postby John Robin Dove » Fri Aug 14, 2015 5:47 am

But in that case surely the object method pauseForText would be called twice. I'm pretty certain it's only called once but I'll test again.
John Robin Dove
 
Posts: 486
Joined: Thu Jan 23, 2014 4:35 am

Re: double user event?!

Postby John Robin Dove » Fri Aug 14, 2015 5:57 am

No you're right there are two calls to pauseForText. Thanks! Now at least I have a better understanding of the problem. I'll let you know how I get on.

UPDATE.

I've put the pcTimer call inside the condition if isPaused = true but this doesn't solve the problem. Maybe I should try including a Timed Delay?

UPDATE 2

Nope the delay makes no difference. I'm running out of ideas. The problem is certainly caused by an excessive number of user events sent to the video object but how can more than one pcTimer be called?! I have checked that isPaused is in fact true when the pcTimer is set.

UPDATE 3

I have not succeeded in discovering how 2 user events are sent instead of 1. I suspect it may be to do with the way my scripts are read one after the other but this is a bit too complex for me to explain here. I could show you on Skype on a day when you have nothing more important to do. For the time being I have found a workaround: as there are always 2 user events that trigger the pauseForText method, never 1 and never 3, I have added a global counter variable with an initial value of 0. pauseForText increments this variable by 1 and pcTimer is only sent when its value is 2; it is then reset to 0. This is not very scientific and could possibly fail on another computer but so far I haven't found a better solution.
John Robin Dove
 
Posts: 486
Joined: Thu Jan 23, 2014 4:35 am

Re: double user event?!

Postby Clifton » Fri Aug 14, 2015 10:12 am

If you are using pgTimer() as a periodic timer, then try setting it to a single timer and restart it on every iteration of its user event. That way you won't have a condition where multiple timers are trying to fire while waiting for other JS processes to finish. If you timer is firing at 200ms and you are "continuously" notifying the video container, you already have a 250ms timer running and it could very well be that a periodic 200ms timer firing with pgTimer() is causing your events to queue up, which gives the appearance of multiples.
Clifton
Site Admin
 
Posts: 732
Joined: Tue Jan 14, 2014 1:04 am

Re: double user event?!

Postby John Robin Dove » Fri Aug 14, 2015 12:43 pm

No I'm using pgTimer as a one off timer. However what you say is probably quite close to the reality. I have thought of a better way to avoid incrementing the counter variable more than once. I'll call it holdCurrentTrigger and give it an initial value of 0. When my method runs for the first time it will set holdCurrentTrigger to the value of currentTrigger (if holdCurrentTrigger = 0 etc.) holdCurrentTrigger can be reset to 0 when the video restarts. So instead of using currentTrigger = currentTrigger + 1 I can use currentTrigger = holdCurrentTrigger + 1 I don't like it much but I think it should work.

You haven't replied to my other post about the video frame 0 picture being shown. Perhaps you didn't see it. It's just below this one in the General Discussion section.
John Robin Dove
 
Posts: 486
Joined: Thu Jan 23, 2014 4:35 am

Re: double user event?!

Postby John Robin Dove » Sat Aug 15, 2015 5:56 am

Just for the record and in case this is useful to anyone else, I have now found a better way of dealing with this. I use an array of boolean values named triggersDone. This is updated in on user event in the field containing the video. As soon as one of my 'triggers' has been sent triggersDone [currentTrigger] is set to true. In this way there is no way that a trigger can be executed more than once because a trigger can only be sent if triggersDone [currentTrigger] = false.
John Robin Dove
 
Posts: 486
Joined: Thu Jan 23, 2014 4:35 am


Return to General Discussion

Who is online

Users browsing this forum: No registered users and 3 guests

cron