using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using System.Threading; using System.Reflection; // Ooganizer Namespaces using Foo.Platform; using System.Windows.Threading; namespace Foo.ClientServices.GUIWPForms { /// /// This class is responsible for creation and deltion of ButtonFormMgr.cs on a /// Dispatcher Thread. ~The Dispatcher is responsible for all the messages being passed /// for the Form Objects, it must be running at all times and created before any forms get /// created. /// [ComVisible(false)] class DispatcherThread { // Member Variables private static Thread s_DispatcherThread = null; private static bool s_DispatcherThreadIsInitialized = false; internal static GUIFormsMgr s_GUIFormsMgr = null; // Declare the Log4net Variable private static log4net.ILog Log = Logger.GetLog4NetInterface(MethodBase.GetCurrentMethod().DeclaringType); /// /// Constructor by default will launch the thread if needed /// static DispatcherThread() { Log.Info(string.Format("{0}() - DispatcherThread() called", MethodBase.GetCurrentMethod().Name)); StartDispatcherThreadIfNeeded(); } /// /// Use this property to set the Dispatcher to running / not running /// public static bool Run { get { return s_DispatcherThreadIsInitialized; } set { if (!value) TerminateDispatcherThreadIfNeeded(); s_DispatcherThreadIsInitialized = value; } } /// /// Message Loop Thread for wpfGUIForms /// private static void DispatcherThreadProc() { // Create ButtonFormMgr Object on this thread *Allow global access to the object* Log.Info(string.Format("{0}() - About to new GUIFormsMgr via DispatcherThread", MethodBase.GetCurrentMethod().Name)); s_GUIFormsMgr = new GUIFormsMgr(Dispatcher.CurrentDispatcher); Log.Info(string.Format("{0}() - GUIFormsMgr DispatcherThread is initialized s_DispatcherThreadIsInitialized is True", MethodBase.GetCurrentMethod().Name)); s_DispatcherThreadIsInitialized = true; // always set to true to allow caller to exit out if (s_GUIFormsMgr != null) { Log.Info(string.Format("{0}() - GUIFormsMgr Launched via DispatcherThread", MethodBase.GetCurrentMethod().Name)); //Enter Dispatcher Message Loop System.Windows.Threading.Dispatcher.Run(); } else { Log.Error(string.Format("{0}() - GUIFormsMgr Launch Failed! Exiting Thread - Major Error must have occured", MethodBase.GetCurrentMethod().Name)); // exit thread - no need to stay here } } /// /// Use this function to start ThreadProc(above) if needed. COM+ can shutdown the thread anytime, /// we need to make sure that the thread is alive BEFORE calling ButtonForms /// private static void StartDispatcherThreadIfNeeded() { if (s_DispatcherThread != null && s_DispatcherThread.IsAlive) { return; } else { s_DispatcherThreadIsInitialized = false; // Start a new Thread so it can become the Message Loop s_DispatcherThread = new Thread(new ThreadStart(DispatcherThread.DispatcherThreadProc)); // GUI components require the thread to be STA; otherwise throws an error s_DispatcherThread.SetApartmentState(ApartmentState.STA); Log.Info(string.Format("{0}() - Starting DispatcherThread...", MethodBase.GetCurrentMethod().Name)); s_DispatcherThread.Start(); Log.Info(string.Format("{0}() - DispatcherThread Started.", MethodBase.GetCurrentMethod().Name)); // Make sure the Application Object is running // (COM will eventually just time out otherwise) //while (!s_DispatcherThreadIsInitialized) // System.Threading.Thread.Sleep(20); // Syncronous call } } /// /// Terminates all ButtonForm Objects and the Message Dispatcher Thread *do this only on shutdown* /// private static void TerminateDispatcherThreadIfNeeded() { if (s_DispatcherThreadIsInitialized) { // Delete s_GUIFormsMgr and all wpfForms from this thread s_GUIFormsMgr.TerminateDISP(); s_GUIFormsMgr = null; s_DispatcherThread.Abort(); s_DispatcherThreadIsInitialized = false; Log.Info(string.Format("{0}() - GUIFormsMgr is DispatcherThread shutdown s_DispatcherThreadIsInitialized is False", MethodBase.GetCurrentMethod().Name)); } } } }