WorkManager (How to handle multiple WorkUnits)

Eyeshot 2021 introduces a new helper class for handling a queue of WorkUnit objects.
For better understanding, we can use the term Operation to indicate the work of every single WorkUnit.
The WorkManager allows performing a single operation or all the operations one after the other synchronously or asynchronously.
When running asynchronously, it notifies you when the single operation is finished or failed rather than when the queue is completed or cancelled.

Here is a code snippet showing an example for loading a list of OBJ files using the WorkManager and the ReadOBJ class.

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(model1);
}

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 = model1.Entities.Count == 0;

    // Adds the content to the scene.
    ro.AddToScene(model1);


    // Fits the scene if it was empty.
    if (fit)
        model1.ZoomFit();
    
    // Refresh        
    model1.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.
}

You can find another sample code using the WorkManager class in the PaperDemo source code sample.

Was this article helpful?
0 out of 0 found this helpful
Have more questions? Submit a request

Comments

0 comments

Please sign in to leave a comment.