Script Engine (Reference) manages the execution, synchronization, and optimization of all scripts, tasks, and expressions within the FrameworX runtime environment.
Advanced Topic: This document provides deep technical insight into the Scripts module execution engine. Most solutions don't require this level of understanding - the default engine behavior handles typical automation requirements automatically.
The Script Engine orchestrates:
Understanding the engine helps when:
Each Script Task runs in its own managed thread:
csharp
// Each task automatically wrapped with:
try
{
// Your task code executes here
// In its own thread context
}
catch (Exception ex)
{
// Automatic exception handling
// Logged but doesn't crash system
}
Trigger Type | Description | Thread Behavior |
---|---|---|
Tag Change | Executes when tag value changes | New thread per change |
Period | Runs at fixed intervals | Reuses thread if available |
Startup | Runs once at module start | Priority thread |
Expression | Inline execution | Thread pool shared |
The engine monitors CPU usage to prevent system overload:
Access runtime metrics via @Script.Task.[TaskName]
namespace:
Property | Type | Description |
---|---|---|
LastExecution | DateTime | When task last ran |
LastCPUTime | TimeSpan | Duration of last execution |
PeakCPUTime | TimeSpan | Maximum execution time recorded |
ExecutionCount | Integer | Total number of executions |
State | Enum | Running, Idle, or Error |
LastException | String | Most recent error message |
Monitor these in:
The engine maintains data consistency across:
Each server-module connection maintains an internal queue:
[Server] → [Queue] → [Module/Client]
↓
Tag Updates
Method Calls
State Changes
Queue Optimization:
<ac:structured-macro ac:name="warning"> ac:rich-text-body Use with Caution: Enabling RaiseAllChanges
forces ALL intermediate values into the queue, potentially causing:
Enable only when:
csharp
// Example of potential issue
for (int i = 0; i < 10000; i++)
{
@Tag.Counter = i; // With RaiseAllChanges, queues 10,000 updates!
}
The engine implements two pre-loading strategies:
First Execution:
Subsequent Executions:
Cache Invalidation:
During execution, the engine predicts object usage:
Limitations:
TK.GetObjectValue()
unpredictableForce objects into memory before use:
csharp
// In ServerStartup task
TK.PreloadTags("Critical.*"); // Preload all Critical tags
TK.PreloadObject(@Alarm.Area1); // Preload specific alarm area
Execution Order:
Aspect | More Pre-Loading | Less Pre-Loading |
---|---|---|
Startup Time | Slower | Faster |
First Execution | Faster | May pause for sync |
Memory Usage | Higher | Lower |
Predictability | Consistent | Variable |
csharp
// Avoid
Thread.Sleep(5000); // Blocks thread
// Prefer
@Tag.DelayedAction = true; // Event-driven
csharp
// Inefficient
for (int i = 0; i < 100; i++)
@Tag["Item" + i] = value;
// Efficient
var updates = new Dictionary<string, object>();
// Prepare all updates
TK.SetMultipleTags(updates); // Single sync
Monitor and manage:
csharp
// Split large tables to avoid timeout
var chunks = TK.SplitDataTable(largeTable, 1000);
foreach (var chunk in chunks)
{
@Tag.PartialData = chunk;
TK.Sleep(100); // Allow queue processing
}
csharp
// Pre-load dynamic references
string tagName = GetDynamicTagName();
TK.PreloadTag(tagName); // Force sync
var value = TK.GetObjectValue("Tag." + tagName);
csharp
// Buffer rapid changes
private DateTime lastUpdate;
private double bufferedValue;
public void ProcessHighFrequency(double value)
{
bufferedValue = value;
if ((DateTime.Now - lastUpdate).TotalMilliseconds > 100)
{
@Tag.Output = bufferedValue;
lastUpdate = DateTime.Now;
}
}
State
propertyLastException
PeakCPUTime