The two examples you mention are easily understood from the way Dynamic updating works. Let us concentrate on Dynamic[x]
. It is sent by the frontend to the kernel and the kernel returns it unevaluated to the frontend, together with the boxes in which the frontend will display. Then the front starts an update procedure over the preemptive link, asking the kernel for the value of x
. So the kernel interrupts what it was doing, evaluates it and returns the value to the frontend.
The two examples strongly rest on the use of Block instead of Module; the variable inside Block is the same as inside Dynamic, so it is not surprising that interference may occur.
Example 1:
x = 2; Dynamic[x]
Block[{x = 1}, Pause[1]; x]
Here the update procedure starts when the kernel is evaluating the Block
command. So the kernel completes the Pause
and then returns the value 1 to the frontend. When the Block was wrapped in PreemptProtect
, the kernel would first have competed the evaluation of the Block command and would then return the value of x
, now again 2.
Example 2:
Dynamic[x = 1, UpdateInterval -> 0.1]
Block[{x = 5}, Pause[1]; x]
The frontend sends the expression x=1
for updating to the kernel when the kernel is evaluating the Pause
statement of the Block
command. So when the Pause is over, the kernel sets x
to 1
and sends that value to the frontend. Then it resumes the evaluation of Block
, with the value 1 instead of 5.
When the Block was wrapped in PreemptProtect
, this would not have happened.
I would like to add another similar example, with the scoping construct Table instead of Block.
x = 10; Dynamic[x]
Table[Pause[1]; x, {x, 1, 5}]
In the Table
command, each second the value of x
changes, so each second the kernel informs the frontend that it must start an update procedure and that is shown in the Dynamic display. But when the evaluation of the Table command is finished, no assignment is done to x
, so the frontend is not informed that it has to start another update procedure, so the Dynamic will display 5 instead of 10. Of course, when we wrap Table in PreemptProtect
, the updating takes place when x
again has the original value 10, so it then looks fine. Nevertheless, even now there can be some interference. First evaluate this command:
x = 10; Dynamic[{x, RandomInteger[{1, 100}]}]
And then:
Table[Pause[1]; x, {x, 1, 5}] // PreemptProtect
During the execution of the above table, the kernel changes the value of x
so it sends an update mesage to the frontend. The resulting update procedure by the frontend is now done when the construction of the Table is finished, so x
will still be displayed as 10. But the random integer will be recomputed as well, so almost surely the display of Dynamic will change.
Edit: SUMMARY
The answer to the question is negative. Even when we wrap Block
in PreemptProtect
, there might be side effects. This is not restricted to Block
; it applies to any scoping construct with dynamic scoping.
Suppose that we have a displayed Dynamic[ expression(x) ]
, and that we have a scoping construct with a local variable x
that uses dynamic scoping. Then the name x
in Dynamic is exactly the same as the name x
in the scoping construct. Whether or not the scoping construct is wrapped in PreemptProtect
, changing the value of x
in the scoping construct forces (by means of a kernel message) the frontend to start a, maybe unwanted, update procedure for Dynamic[ expression(x) ]
, and this updating procedure may give a changed display of Dynamic[ expression(x) ]
, as in the above example. The only effect of PreemptProtect
is the time when the kernel executes the update call. Without PreemptProtect
very likely during the evaluation of the scoping construct, otherwise when the evaluation of the scoping construct is finished.
On the other hand, when we wrap the scoping construct in PreemptProtect
, the evaluation of the scoping construct cannot be influenced by preemptive calls, and therefore it will always return the expected result.