Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I guess I have to try harder and focus more but timed evaluation always frustrates me.

I will show the issue on simple example of delayed trigger.

 ClearAll@time; time = 0;
 CreateScheduledTask[time++;, {1, 5}]
 StartScheduledTask@ScheduledTasks[];

 DynamicWrapper[Dynamic@time, 
                If[time === 5, RemoveScheduledTask[ScheduledTasks[]]; Print["end"]]]
1... 2... 3... 4... 5 "end" (*so it works OK*)

In general one may want to scope such procedure:

DynamicModule[{x},
ClearAll@x;

Column[{Button["start", x = 0;
                         RemoveScheduledTask[ScheduledTasks[]];
                         StartScheduledTask@CreateScheduledTask[x++;, {1, 5}]],
         DynamicWrapper[Dynamic@x, If[x === 5, Print@1]]   
          }] ]

output before clicking:

FE`x$$number (*as expected*)

output after clicking:

0 (*and it does not change*)

We can see that the only procedure that was enabled was x = 0;.

I was suspecting problems because ScheduledTasks are not related to FrontEnd while DynamicModule is.

What is interesting is that changing DynamicModule to Module fixes the problem.

The question are:

  • What am I missing in case of DynamicModule? I've seen Module variable scoping in ScheduledTasks but I couldn't use it for my purpose. (*I've added ClearAll but it does not seem to make any difference.

  • Schould I use Module even if this is only a minimal example of the code that will be implemented in larger cdf? Moreover, John Fultz reminded couple of times (e.g. here) that such constructs are incorrect.

share|improve this question
    
@JacobAkkerboom :) any thoughts? –  Kuba Dec 5 '13 at 13:02
    
unfortunately I don't know much about any of this :( –  Jacob Akkerboom Dec 5 '13 at 13:20
1  
My guess is that the update mechanism of Dynamic does not generally know about things changed via the scheduled task mechanism, particularly when you localize using DynamicModule, which means that the localized variable is owned by the FrontEnd. One way that works is to use something like Dynamic[x, UpdateInterval -> 1] instead of just Dynamic[x]. –  Leonid Shifrin Dec 5 '13 at 14:46

1 Answer 1

up vote 7 down vote accepted

Updated

This happens because your DynamicModule returns a dynamic object of which x is passed on to the front-end before the scheduled task starts, so the front-end-x cannot be modified anymore by any process (more details at the end).

The problem can be further simplified. This works:

RemoveScheduledTask@ScheduledTasks[];
DynamicModule[{x = 0}, RunScheduledTask[x++, {1, 5}]; Print@Dynamic@x;];

but this does not (at least not how one would expect):

RemoveScheduledTask@ScheduledTasks[];
DynamicModule[{x = 0}, RunScheduledTask[x++, {1, 5}]; Dynamic@x]

Examining the second one:

RemoveScheduledTask[ScheduledTasks[]];
d = DynamicModule[{x = 0}, Print[HoldForm@x -> x]; 
RunScheduledTask[x++, {1, 5}]; Dynamic[HoldForm@x -> x]]
 x$1725 -> 0  (* the real name of x inside DynamicModule & the sched.task *)

 FE`x$$18 -> 0 (* the displayed x as returned from DynamicModule *)

Clearly, the returned x has nothing to do with the x used in the scheduled task.

As OP realized, Module works where DynamicModule does not. The same analysis as above:

RemoveScheduledTask[ScheduledTasks[]];
d = Module[{x = 0}, Print[HoldForm@x -> x]; 
RunScheduledTask[x++, {1, 5}]; Dynamic[HoldForm@x -> x]]
x$1740 -> 0  (* the real name of x inside DynamicModule & the sched.task *)

x$1740 -> 0  (* the displayed dynamic value of x as returned from DynamicModule *)

The two variables are not decoupled, so the scheduled task will modify the same variable that is displayed. The problem here is that the variable that is actually displayed and modified dynamically (x$1740) are not owned by the front-end, though it should be according to John Fultz's explanation. See below for a better solution.

Better understanding evaluation sequence

As Leonid has pointed it out, the returned dynamic value of a DynamicModule is owned by the frontend:

DynamicModule[{x}, Print@Dynamic@x; Dynamic@x]
x$4513     (* printed *)

FE`x$$88   (* returned *)

One can change the first one from the outside as x$4513 = 99, but not the second one, so scheduled tasks failed.

Digging deeper, I managed to get to the depths of the problem. The main reason while the returned x does not update is because when the return value of the DynamicModule is returned and displayed on screen, it is passed on to the front end without evaluation, and gets renamed from x$4513 to x$$88. Only after it is displayed will the front end look after how to update x, however, the internal scheduled task has already been called before returning Dynamic[x] from the DynamicModule, and it still refers to x$4513, so the two references to x gets decoupled and will never be linked anymore.

According to this hypothesis, delaying the scheduled task AFTER the returned value is displayed should work. The correct method for this is to use Initialization, that is evaluated right after the returned value of a DynamicModule is displayed:

RemoveScheduledTask[ScheduledTasks[]];
d = DynamicModule[{x = 0},
  Print["In DM: ", HoldForm@x -> x];
  Dynamic[x, TrackedSymbols :> {x}],
  Initialization :> (Print["initialized"]; 
    RunScheduledTask[x++; Print["In ST: ", HoldForm@x -> x], {.5, 3}];)
  ]

When evaluated, one can see that the two Print statements refer to different variables:

In ST: FE`x$$11->1

In DM: x$1729->0 

meaning that the scheduled task (ST printing) now correctly uses the front-end variable instead of the kernel variable (DM printing)! For the whole thing to work, one needs an extra TrackedSymbols :> {x} in Dynamic, or something similar, to tell the front-end what variable/trigger should be checked. Any of the followings should work:

Dynamic[x, TrackedSymbols :> {x}]
Dynamic@{x}
Dynamic[x, UpdateInterval -> .1]

but not this:

Dynamic@x
share|improve this answer
    
Short answer: use Module instead of DynamicModule. –  István Zachar Dec 5 '13 at 15:10
    
But what with what JohnFults has said? Isn't Module behaviour some kind of side effect in this case? I have to think about this more :) p.s. variables in DynamicModule seem to have double $ (e.g. x$$123) and in Module single $. Is it different in your case? –  Kuba Dec 6 '13 at 8:45
    
@Kuba Does the edit provide a better understanding of the case? I still don't know exactly why the Module-based version is to be avoided, but I fully trust the words of John Fultz. Would be nice if he could throw in some extra information... –  István Zachar Dec 6 '13 at 14:57
1  
I like the update :) great you've managed to figure it out. There are always problems with timed procedures/precedence/or evaluation order (at least to me) but this is important part of GUI creation and such problems should already have been discussed in possible issues sections. Thanks again. –  Kuba Dec 7 '13 at 6:42
    
@Kuba, fine by me :) –  István Zachar May 5 at 13:02

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.