Overview
A WorkUnit represents a long-running operation in Eyeshot.
WorkUnits are used throughout the SDK to execute tasks such as file import and export, geometry processing, meshing, triangulation, simulation, and other computationally intensive operations.
Applications can also derive from WorkUnit to implement custom long-running tasks, using the same execution model adopted internally by Eyeshot.
A WorkUnit supports:
- synchronous and asynchronous execution
- progress reporting through
IProgress<T> - cooperative cancellation
- lifecycle handling through virtual methods
Execution methods
A WorkUnit can be executed either synchronously or asynchronously, depending on the application requirements.
Synchronous execution
workUnit.DoWork();This method executes the WorkUnit synchronously on the calling thread. Failures are surfaced as standard exceptions.
Asynchronous execution
await workUnit.DoWorkAsync();DoWorkAsync executes the WorkUnit asynchronously using the Task-based Asynchronous Pattern (TAP).
This execution mode:
- integrates naturally with
async/await - does not block the calling thread
- supports cancellation and progress reporting
- propagates failures through the returned
Task
Asynchronous execution example (recommended pattern)
The following example shows a complete and recommended pattern for executing a WorkUnit asynchronously directly (outside a Workspace), including:
-
async/await - progress reporting
- cancellation
- optional lifecycle hook invocation (when required by the WorkUnit)
private async Task ExecuteWorkUnitAsync(WorkUnit workUnit, object sender)
{
// Create a cancellation token source
using var cts = new CancellationTokenSource();
// Create a progress handler
var progress = new Progress<ProgressChangedEventArgs>(args =>
{
// Handle progress updates here
Console.WriteLine($"{args.ProgressPercentage}% - {args.UserState}");
});
try
{
// Execute the WorkUnit asynchronously
await workUnit.DoWorkAsync(progress, cts.Token);
// Invoke the completion lifecycle hook if the WorkUnit relies on it
workUnit.WorkCompleted(sender);
}
catch (OperationCanceledException)
{
// Invoke the cancellation lifecycle hook if required
workUnit.WorkCancelled(sender);
throw;
}
catch (Exception)
{
// Invoke the failure lifecycle hook if required
workUnit.WorkFailed(sender);
throw;
}
}The sender parameter should represent the logical parent of the WorkUnit, such as a Document or other application-level object.
Lifecycle hooks should be invoked only when the WorkUnit implementation relies on them (for example, to integrate results into a Document). When a WorkUnit is executed through a Workspace, lifecycle hooks are invoked automatically by the Workspace execution pipeline.
Progress reporting
A WorkUnit reports progress through the IProgress<ProgressChangedEventArgs> interface.
During asynchronous execution, progress notifications are delivered to the provided progress handler, which can update UI elements, logs, or other observers.
To simplify common scenarios, WorkUnit provides helper methods such as UpdateProgress, UpdateProgressAndCheckCancelled, UpdateProgressTo100, and their parallel variants. These helpers standardize progress reporting and cooperative cancellation, including support for parallel loops.
The WorkUnit.ProgressChanged event is maintained for backward compatibility but is considered legacy. New implementations should rely on IProgress<T>.
Cancellation
WorkUnits support cooperative cancellation through CancellationToken.
The WorkUnit implementation is responsible for periodically checking the token and stopping execution when cancellation is requested.
Lifecycle hooks
WorkUnits expose the following virtual lifecycle methods:
WorkCompleted(object sender)WorkCancelled(object sender)WorkFailed(object sender)
These methods can be overridden by derived WorkUnits to finalize execution or integrate results into a higher-level component (for example, a Document).
When executed through a Workspace, lifecycle hooks are invoked automatically by the execution pipeline.
Custom WorkUnits
Applications can define custom WorkUnits by deriving from the WorkUnit base class.
Custom WorkUnits can:
- encapsulate application-specific long-running logic
- support synchronous and asynchronous execution
- participate in progress reporting and cancellation
- override lifecycle hooks to integrate results
This makes WorkUnit a general-purpose abstraction for long-running operations, not limited to file import or export.
WorkUnit execution context
A WorkUnit can be executed:
- directly, by calling its execution methods
- through a Workspace, which provides UI integration such as the native Eyeshot progress bar and cancellation support
The execution context determines how lifecycle hooks are triggered, but does not change the WorkUnit execution model itself.
Comments
Please sign in to leave a comment.