-
Notifications
You must be signed in to change notification settings - Fork 3
plugin sdk threading
Plugins use a dedicated engine thread for entity operations and lifecycle methods. Understanding the threading model is essential for writing correct, performant plugin code.
Plugin starts on engine thread
|
OnPluginLoaded and OnPluginStart run on engine thread
|
Engine write operations must run on engine thread
|
External threads must queue work to engine thread
Key principles:
- Write operations (create, update, delete entities) must run on the engine thread
- Entity cache reads are thread-safe but have I/O considerations (see below)
- Lifecycle methods
OnPluginLoadedandOnPluginStartrun on the engine thread -
Disposemay be called from any thread - Most other callbacks (event handlers, query handlers, request handlers) run on background threads
- External callbacks (
System.Timers.Timer, Task continuations, ThreadPool work items) run on different threads
GetEntity and I/O:
-
GetEntity(guid)orGetEntity(guid, query: true)- May query the server if entity is not cached (I/O operation) -
GetEntity(guid, query: false)- Returns only from cache, returns null if not cached
Every plugin has a dedicated engine thread where entity operations are performed. This thread:
- Executes lifecycle methods
OnPluginLoadedandOnPluginStart - Processes entity updates and transactions
- Does not have a
System.Threading.SynchronizationContext
Most other callbacks run on background threads, not the engine thread:
- Event handlers (
EventReceived,ActionReceived,EntitiesInvalidated) run on the event raising thread - Query handlers (
OnQueryReceived) run on a report processing thread - Request handlers (added via
AddRequestHandler) run on an async worker thread
Engine thread constraints:
- Avoid blocking I/O operations (network calls, file operations, database queries)
- Avoid long-running computations
- Use only for entity operations and configuration changes
- Perform I/O and heavy processing on background threads
Warning
If the engine thread is blocked for too long, Security Center will detect the plugin as unresponsive and terminate the GenetecPlugin.exe process. Keep engine thread operations brief.
Use these methods to marshal work from external threads to the engine thread.
| Method | Behavior | Returns |
|---|---|---|
QueueUpdate(Action) |
Queues action to engine thread, returns immediately | IAsyncResult |
QueueUpdateAndWait(Action) |
Queues action and blocks until completed | IAsyncResult |
Use QueueUpdate when you do not need to wait for the result:
// Example: Timer callback runs on a ThreadPool thread
private void OnTimerElapsed(object sender, ElapsedEventArgs e)
{
// Queue to engine thread - returns immediately
Engine.QueueUpdate(() =>
{
var entity = Engine.GetEntity<CustomEntity>(m_entityGuid);
entity.RunningState = State.Running;
});
// Execution continues immediately without waiting
}Use QueueUpdateAndWait when you need to wait for a write operation to complete before continuing:
// Example: External thread needs to update an entity and confirm success
private bool TryUpdateEntityState(Guid entityGuid, State newState)
{
bool success = false;
Engine.QueueUpdateAndWait(() =>
{
try
{
var entity = Engine.GetEntity<CustomEntity>(entityGuid);
entity.RunningState = newState;
success = true;
}
catch (Exception ex)
{
Logger.TraceError(ex, "Failed to update entity state");
}
});
return success;
}Use the IsEngineThread property to determine if the current thread is the engine thread:
private void ProcessData(ExternalData data)
{
if (Engine.IsEngineThread)
{
// Already on engine thread - safe to modify entities
UpdateEntity(data);
}
else
{
// On external thread - must queue write operations to engine thread
Engine.QueueUpdate(() => UpdateEntity(data));
}
}This check is required for write operations (create, update, delete entities) and when using the TransactionManager. Entity cache reads with GetEntity(guid, query: false) are thread-safe and do not require queueing. However, GetEntity(guid) with default behavior may trigger server I/O if the entity is not cached.
Since QueueUpdate returns immediately without waiting, exceptions thrown inside the queued action do not propagate to the calling code. Handle exceptions within the action itself:
Engine.QueueUpdate(() =>
{
try
{
var entity = Engine.GetEntity<CustomEntity>(entityGuid);
entity.RunningState = State.Running;
}
catch (Exception ex)
{
Logger.TraceError(ex, "Failed to update entity");
}
});Since QueueUpdateAndWait waits for completion, exceptions propagate to the caller:
try
{
Engine.QueueUpdateAndWait(() =>
{
var entity = Engine.GetEntity<CustomEntity>(entityGuid);
entity.RunningState = State.Running;
});
}
catch (SdkException ex)
{
Logger.TraceError(ex, "Operation failed");
}The engine thread does not have a System.Threading.SynchronizationContext. This means that after an await, the continuation will not return to the engine thread automatically.
// WRONG - continuation runs on thread pool, not engine thread
private async void OnPluginLoaded()
{
var data = await ExternalApi.GetDataAsync();
ProcessData(data); // Runs on wrong thread!
}
// CORRECT - queue entity updates back to engine thread
protected override void OnPluginLoaded()
{
Task.Run(async () =>
{
var data = await ExternalApi.GetDataAsync();
Engine.QueueUpdate(() => ProcessData(data));
});
}- Plugin SDK Lifecycle - When lifecycle methods are called
- Plugin SDK Events - Event handler threading
- Plugin SDK Request Manager - Request handler threading
- SDK Transactions - Transaction usage with threading
-
Security Center SDK Developer Guide Overview of the SDK framework and how to build integrations with Security Center.
-
Platform SDK
- Overview Introduction to the Platform SDK and core concepts.
- Connecting to Security Center Step-by-step guide for connecting and authenticating with the SDK.
- SDK Certificates Details certificates, licensing, and connection validation.
- Referencing SDK Assemblies Best practices for referencing assemblies and resolving them at runtime.
- SDK Compatibility Guide Understanding backward compatibility and versioning in the SDK.
- Entity Guide Explains the core entity model, inheritance, and how to work with entities.
- Entity Cache Guide Describes the engine's local entity cache and synchronization.
- Transactions Covers batching operations for performance and consistency.
- Events Subscribing to real-time system events.
- Actions Sending actions to Security Center.
- Security Desk Displaying content on monitors, reading tiles, sending tasks, and messaging operators.
- Custom Events Defining, raising, and subscribing to custom events.
- ReportManager Querying entities and activity data from Security Center.
- ReportManager Query Reference Complete reference of query types, parameters, and response formats.
- Privileges Checking, querying, and setting user privileges.
- Partitions Entity organization and access control through partitions.
- Logging How to configure logging, diagnostics, and debug methods.
-
Plugin SDK
- Overview Introduction to plugin architecture and capabilities.
- Certificates SDK certificate requirements for plugin roles.
- Lifecycle Initialization and disposal patterns.
- Threading Threading model, QueueUpdate, and async patterns.
- State Management Reporting plugin health and diagnostics.
- Configuration Configuration storage and monitoring.
- Restricted Configuration Secure credential storage and admin-only configuration.
- Events Event subscription and handling.
- Queries Query processing and response handling.
- Request Manager Request/response communication with clients.
- Database Database integration and schema management.
- Entity Ownership Understanding plugin-owned entities, running state management, and ownership release.
- Entity Mappings Using EntityMappings for plugin-specific configuration and external system integration.
- Server Management High availability and server failover.
- Custom Privileges Defining and enforcing custom privileges.
- Custom Entity Types Defining and managing plugin-specific entity types.
- Resolving Non-SDK Assemblies Handling third-party dependencies in plugins and workspace modules.
- Deploying Plugins Registering and deploying plugins and workspace modules.
- .NET 8 Support Building plugins with .NET 8 and .NET Standard compatibility.
-
Workspace SDK
- Overview Introduction to client-side UI extensions for Security Desk and Config Tool.
- Certificates SDK certificate requirements for workspace modules.
- Creating Modules Module lifecycle, registration patterns, and assembly resolution.
- Tasks Executable actions, home page entries, and programmatic invocation.
- Pages Page content, lifecycle, descriptors, and navigation.
- Components Dashboard widgets, tiles, maps, credentials, and content builders.
- Tile Extensions Custom tile widgets, views, and properties panels.
- Services Built-in services for dialogs, maps, alarms, badges, and more.
- Contextual Actions Right-click context menu extensions.
- Options Extensions Custom settings pages in application preferences.
- Configuration Pages Entity configuration pages for Config Tool.
- Monitors Multi-monitor support and shared components.
- Shared Components Using monitor and workspace shared UI components.
- Commands Command execution, evaluation, and interception.
- Extending Events Adding custom fields to Security Center events.
- Map Extensions Custom map objects, layers, and providers.
- Timeline Providers Custom timeline event sources for video playback.
- Image Extractors Custom image sources for cardholder photos and custom fields.
- Credential Encoders Encoding credentials with custom encoder components.
- Cardholder Fields Extractors Importing cardholder data from external sources.
- Content Builders Building and customizing tile content in Security Desk.
-
Macro SDK
- Overview How macros work, creating and configuring macro entities, automation, and monitoring.
- Developer Guide Developing macro code with the UserMacro class and Security Center SDK.
-
- Getting Started Setup, authentication, and basic configuration for the Web SDK.
- Referencing Entities Entity discovery, search capabilities, and parameter formats.
- Entity Operations CRUD operations, multi-value fields, and method execution.
- Partitions Managing partitions, entity membership, and user access control.
- Custom Fields Creating, reading, writing, and filtering custom entity fields.
- Custom Card Formats Managing custom credential card format definitions.
- Actions Control operations for doors, cameras, macros, and notifications.
- Events and Alarms Real-time event monitoring, alarm monitoring, and custom events.
- Incidents Incident management, creation, and attachment handling.
- Reports Activity reports, entity queries, and historical data retrieval.
- Performance Guide Optimization tips and best practices for efficient API usage.
- Reference Entity GUIDs, EntityType enumeration, and EventType enumeration.
- Under the Hood Technical architecture, query reflection, and SDK internals.
- Troubleshooting Common error resolution and debugging techniques.
- Media Gateway Guide Setup and configuration of the Media Gateway role for video streaming.
- Developer Guide Complete guide to integrating GWP for live and playback video streaming.
- API Reference Full API documentation with interfaces, methods, properties, and events.
- Sample Application Comprehensive demo showcasing all GWP features with timeline and PTZ controls.
- Multiplexing Sample Multi-camera grid demo using a shared WebSocket connection.