🌶️ WorkManager (How to handle multiple WorkUnits)

Eyeshot 2021 introduces a new helper class designed to handle a queue of WorkUnit objects more efficiently.
To facilitate understanding, we use the term Operation to refer to the work carried out by each individual WorkUnit.
The WorkManager class enables the execution of either a single operation or all operations in the queue, either synchronously or asynchronously. If an object that implements the ISupportWorkManager interface is provided as a parameter, asynchronous execution becomes possible.
In asynchronous mode, you receive notifications about the completion or failure of each individual operation, rather than waiting for the entire queue to finish or be canceled.

Below is a code snippet that illustrates an example of loading a list of OBJ files using the WorkManager and the ReadOBJ classes.

private WorkManager<ReadOBJ> _readMultiObj;

private void ReadObjFiles(string[] filePaths)
{
    // Creates the WorkManager if needed
    if (_readMultiObj == null)
    {
        _readMultiObj = new WorkManager<ReadOBJ>();

        // Listens to WorkManager events
        _readMultiObj.WorkUnitCompleted += ReadMultiObj_WorkUnitCompleted;
        _readMultiObj.WorkUnitFailed    += ReadMultiObj_WorkUnitFailed;
        _readMultiObj.QueueCompleted    += ReadMultiObj_QueueCompleted;
        _readMultiObj.QueueCancelled    += ReadMultiObj_QueueCancelled;
    }

    // Appends a reader for each file
    for (int i = 0; i < filePaths.Length; i++)
        _readMultiObj.AppendToQueue(new ReadOBJ(filePaths[i]));

    // Runs all the operations asynchronous if the WorkManager is not running yet.
    _readMultiObj.RunAll(design1);
}

private void ReadMultiObj_WorkUnitCompleted(object sender, WorkUnitEventArgs e)
{
    // Operation completed

    Debug.Assert(e.WorkUnit.Status == workUnitStatus.Completed);

    ReadOBJ ro = (ReadOBJ) e.WorkUnit;

    // Adds here some logic for checking ReadOBJ content (e.g. applying transformations to the entities).

    bool fit = design1.Entities.Count == 0;

    // Adds the content to the scene.
    ro.AddTo(design1);


    // Fits the scene if it was empty.
    if (fit)
        design1.ZoomFit();
    
    // Refresh        
    design1.Invalidate();

    // You can choose to remove the WorkUnit to free-up memory.
    _readMultiObj.RemoveFromQueue(ro);
}

private void ReadMultiObj_WorkUnitFailed(object sender, WorkUnitEventArgs e)
{
    // Operation Failed

    Debug.Assert(e.WorkUnit.Status == workUnitStatus.Failed);

    WriteLog(e.WorkUnit.Log);
}

private void ReadMultiObj_QueueCompleted(object sender, EventArgs e)
{
    // All Operations completed

    // Removes event handlers
    _readMultiObj.WorkUnitCompleted -= ReadMultiObj_WorkUnitCompleted;
    _readMultiObj.WorkUnitFailed    -= ReadMultiObj_WorkUnitFailed;
    _readMultiObj.QueueCompleted    -= ReadMultiObj_QueueCompleted;
    _readMultiObj.QueueCancelled    -= ReadMultiObj_QueueCancelled;

    // Dispose the WorkManager
    _readMultiObj.Dispose();
    _readMultiObj = null;
}

private void ReadMultiObj_QueueCancelled(object sender, WorkUnitEventArgs e)
{
    // Operation Cancelled

    Debug.Assert(e.WorkUnit.Status == workUnitStatus.Cancelled);

    // When the WorkManager starts again, it will get the first WorkUnit with status Idle or Cancelled.

}

private void WriteLog(string message)
{
    // Code for logging here.
}

In the PaperDemo source code sample, you can find another example of how to use the WorkManager class.

Was this article helpful?
0 out of 0 found this helpful

Comments

0 comments

Please sign in to leave a comment.

Articles in this section

See more