/// <summary>
 /// Terminate and dispose the message loop.
 /// </summary>
 /// <remarks>This function blocks until the message loop terminates</remarks>
 public void Dispose()
 {
     StopAsync();
     Join();
     m_instance = null;
     m_thread   = null;
 }
 /// <summary>
 /// Construct the message loop.
 /// </summary>
 /// <param name="onStart">Action to run when loop starts (inside the message loop)</param>
 /// <param name="onExitAsync">Action to run when loop terminates (inside the message loop). Should return an async task which completes when terminated</param>
 /// <param name="threadName">Thread name if specified</param>
 /// <param name="isBackground">Is the thread a background thread?</param>
 /// <returns>Object when disposed, the message loop will initiate termination sequence</returns>
 public ThreadedMessageLoop(Action onStart = null, Func <Task> onExitAsync = null, bool isBackground = true, string threadName = null)
 {
     m_threadName   = threadName;
     m_isBackground = isBackground;
     m_instance     = new MessageLoopDelegate();
     m_instance.SetOnExitAsync(onExitAsync);
     if (onStart != null)
     {
         m_instance.SetOnStart(() =>
         {
             onStart();
             return(true);
         });
     }
 }