DynamoDS/Dynamo — pull request #2941 by Benglin (2014-11-03 04:50:45+00:00)
Title: Fixed deadlock in VisualizationManagerRenderComplete

Background
-----
```VisualizationManagerRenderComplete``` is being called on the context of ```ISchedulerThread``` as shown:

DynamoCore.dll!Dynamo.Controls.Watch3DView.VisualizationManagerRenderComplete...
DynamoCore.dll!Dynamo.VisualizationManager.OnRenderComplete(object sender, Dy...
DynamoCore.dll!Dynamo.VisualizationManager.OnNodeModelRenderPackagesReady(Dyn...
DynamoCore.dll!Dynamo.Core.Threading.AsyncTask.HandleTaskCompletion() Line 20...
DynamoCore.dll!Dynamo.Core.Threading.DynamoScheduler.ProcessTaskInternal(Dyna...
DynamoCore.dll!Dynamo.Core.Threading.DynamoScheduler.ProcessNextTask(bool wai...
DynamoCore.dll!Dynamo.Core.Threading.DynamoSchedulerThread.ThreadProc() Line ...

In ```VisualizationManagerRenderComplete``` method, ```Dispatcher.Invoke``` is being used to execute a ```DelegateCommand``` on the UI thread. While is is generally okay, it will cause a deadlock if it happens during shutdown, primarily because the UI thread will wait for ```ISchedulerThread``` to finish its job and terminate gracefully:

```cs
class DynamoScheduler
{
internal void Shutdown()
{
schedulerThread.Shutdown(); // Wait for scheduler thread to end.
}
}

class DynamoSchedulerThread : ISchedulerThread
{
public void Shutdown()
{
internalThread.Join(); // Wait for background thread to terminate.
}
}
```

The above results in ```internalThread.Join``` to be held up because ```DynamoSchedulerThread``` is waiting for ```Dispatcher.Invoke``` to return, while ```Dispatcher.Invoke``` cannot execute because UI thread is being held up at ```internalThread.Join``` statement. To avoid possibility of a deadlock, ```Dispatcher.BeginInvoke``` should be used instead (it does not wait for the ```Action``` to be dispatched for execution, it returns immediately after queueing the ```Action``` on the main ```Dispatcher```). This way ```VisualizationManagerRenderComplete``` returns immediately, releasing ```internalThread.Join``` call.

Hi @ikeough, please have a look at this. Thanks!