🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
Periodic action
This page was created by Lars.olofsson on 2019-06-10. Last edited by Wikiadmin on 2026-07-29.

A periodic action is a ViewModel action that runs repeatedly in the client while its Disabled expression evaluates to false; use it when a ViewModel must react automatically to a condition or poll for a server-side change.

How periodic actions work

You define a periodic action in the ViewModel Editor by configuring an action with an interval and a Disabled expression.

  • Interval is the repeat delay in milliseconds.
  • Disabled expression is an OCL expression evaluated to decide whether the action may run.
  • The action repeats while the Disabled expression is false.
  • When the Disabled expression becomes true, the action stops repeating.

For each execution, the client calls MDrivenServer. A periodic action is therefore client-side polling: it runs only while the client has the ViewModel open and active. It is not a scheduled background job on MDrivenServer. For work that must run independently of an open client, use MDrivenServer periodic server-side actions or serverside jobs.

Configure a periodic action

  1. Open the ViewModel in the ViewModel Editor.
  2. Select or create the ViewModel action that should run automatically.
  3. Set its Interval to the required delay in milliseconds.
  4. Enter a Disabled expression that becomes true when the action no longer needs to run.
  5. Define the action expression or selected standard action that performs the work.
  6. Save the model and test the ViewModel with the condition both active and inactive.

For example, an action that should run only while an order is waiting for a number can use:

Interval: 2000
Disabled expression: self.State<>'AssignNumber'
Action expression: selfVM.Refresh

The action runs every two seconds while self.State='AssignNumber'. Once the state changes, the Disabled expression becomes true and polling stops.

Choose an appropriate use

Use a periodic action when the ViewModel needs to perform a repeated client-side check or update. Common uses include:

  • Navigate automatically after a database change, such as when a current user has been set after login.
  • Start an action, such as a search, after a specified condition or time has been reached.
  • Refresh a WPF view with selfVM.Refresh while the root object may change on the server.
  • Update a transient ViewModel value, collection, or association shown on the screen.
  • Save dirty data at intervals when you have a specific autosave requirement. For the recommended autosave approach and its configuration, see Auto save.

Do not use a periodic action to maintain a calculated value when all involved attributes belong to modeled classes. Use a derived settable attribute instead; it is more reliable, faster, and easier to understand. A periodic action is appropriate when the value being updated is a ViewModel variable, value, or collection that is not automatically recalculated with the modeled attributes.

Example: synchronize a ViewModel value

Assume A is a persisted attribute and B is a derived value. You want to copy the current value of B to A after B changes.

Configure the action as follows:

Property Value Result
Interval X milliseconds The action waits X milliseconds between checks while enabled.
Disabled expression self.A=self.B The action is disabled when the values already match and enabled when they differ.
Action expression self.A:=self.B The persisted attribute receives the current derived value.

When B changes and no longer equals A, the Disabled expression becomes false. At the next interval, the action assigns B to A. The values then match, the Disabled expression becomes true, and the periodic action stops.

Always provide a stopping condition

A periodic action must have a Disabled expression. If it has no Disabled expression, model validation reports an error similar to:

The column XXXXX is a PeriodicAction without a Disabled-expression. When using periodic actions, you must be able to stop it.

A Disabled expression of false satisfies this validation requirement, but it never stops the action. Use it only when you deliberately require continuous execution and have selected an interval that is safe for the expected number of clients.

Avoid intervals shorter than several seconds, especially intervals below 5000 milliseconds, unless the Disabled expression reliably and quickly becomes true. For example, an interval of 100 milliseconds can make every open client call MDrivenServer ten times per second until the action stops. This can consume client and server CPU and produce continuous network traffic.

After testing a periodic action, inspect the browser's network tab to confirm that requests stop when the Disabled expression becomes true. Also test the case where the condition never changes, so that you understand the sustained request rate.

Repair existing actions missing a Disabled expression

If an existing model produces many missing-Disabled-expression validation errors, you can use the model debugger to assign false to affected actions:

Column.allInstances->select(c | c.IsAction and (c.ActionPeriodicityMillisec <> -1) and c.ExpressionForReadOnly.isNullOrEmpty and c.ActionToExecute.EnableExpression.isNullOrEmpty)->forEach(c|c.ExpressionForReadOnly := 'false')

This expression removes the immediate validation errors, but it creates actions that do not stop. Review every affected action afterward and replace false with a condition that disables polling when no work remains.

Client refresh with server-side work

A common pattern combines a client periodic action with a server-side periodic action:

  1. The client changes an order state to 'AssignNumber'.
  2. A server-side periodic action selects orders in that state, assigns a number, changes the state to 'NumberAssigned', and saves the result.
  3. While the order remains in 'AssignNumber', the client periodic action calls selfVM.Refresh.
  4. When the refreshed order reaches 'NumberAssigned', the client Disabled expression becomes true and refresh polling stops.

This pattern lets the server serialize work such as number assignment while the client displays progress. Where the state and number attributes use the Realtime tagged value, the server-side guidance notes that client refresh polling may no longer be needed. See MDrivenServer periodic server-side actions for the complete server-side pattern and the recommendation to combine it with SysAsyncTicket where appropriate.

See also