Search code examples
powerapps

Event Handling and Thread Safety in PowerApps


Powerapps supports timer events in addition to user events. This introduces the possibility of concurrent timers accessing global variables or collections. Documentation provides no information on event handling (concurrent vs sequential, message pump vs callback). Powerapps community forum is silent. Am posting here to inquire with the SO community whether testing has been done on this already before re-inventing the wheel. (SO search revealed no relevant topics, would happily stand corrected if there are).

Example use case is separating and backgrounding barcode registration and data transmission using timers. I.e. imagine a grocery store check out.

Will report back on findings if no existing information available.


Solution

  • PowerApps is built on JavaScript, which is single threaded (*), based on callbacks. Every expression is executed as a single "unit of execution", so if you have something like:

    UpdateContext({ a: 1, b: 2 }); UpdateContext({ c: a + b })
    

    You can count on the fact that the 'a' and 'b' will be initialized together (without being interrupted). You cannot, however, rely on the fact that the second UpdateContext call will be made before anything happens that may change the values of 'a' or 'b' (such as a timer's OnTimerEnd expression) - although it's very unlikely that this will happen.

    For the specific example of timers, if you have two of them with this expression:

    Set(globalVarA, globalVarA + 1)
    

    It's possible (although quite unlikely, especially for this kind of simple operation) that the value of 'globalVarA + 1' will be calculated for the two timers before the internal implementation of the Set function is called to update the value of that variable (in which case the app would "lose" one of the increments).

    A scenario where a problem is more likely to happen is when you have calls to data sources (which involve network calls that are slower). For example, if you have this expression on two timers:

    Set(oldVar1, var1);
    Patch(dataSource, record, changes);
    Set(var1, oldVar1 + 1)
    

    Then the likelihood of a race condition happening increases by a lot.

    Hope this helps!

    (*) Currently there is some very limited usage of JS worker threads, so the app isn't technically completely single threaded, but that should not affect expressions that you write.