DynamicRendererThreadManager.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Core / CSharp / System / Windows / Input / Stylus / DynamicRendererThreadManager.cs / 1 / DynamicRendererThreadManager.cs

                            //---------------------------------------------------------------------------- 
//
// File: DynamicRendererThreadManager.cs
//
// Description: 
//      Dynamic Renderering Dispatcher - Provides shared Dispatcher for off application
//      Dispatcher inking support. 
// 
// Copyright (C) 2003-2004 by Microsoft Corporation.  All rights reserved.
// 
//---------------------------------------------------------------------------

using System;
using System.Diagnostics; 
using System.Collections.Specialized;
using System.Collections.Generic; 
using System.Windows; 
using System.Windows.Input;
using System.Windows.Media; 
using System.Threading;
using System.Windows.Threading;
using MS.Utility;
using System.Security; 
using System.Security.Permissions;
using MS.Internal; 
 
namespace System.Windows.Input.StylusPlugIns
{ 
    /// 
    /// Manager for the Dispatcher.ShutdownStarted event.
    /// 
    // Note: this class should have the same visibility (public / internal / 
    // private) as the event it manages.  If the event is not public, change
    // the visibility of this class accordingly. 
    internal sealed class DispatcherShutdownStartedEventManager : WeakEventManager 
    {
        #region Constructors 

        //
        //  Constructors
        // 

        private DispatcherShutdownStartedEventManager() 
        { 
        }
 
        #endregion Constructors

        #region Public Methods
 
        //
        //  Public Methods 
        // 

        ///  
        /// Add a listener to the given source's event.
        /// 
        /// 
        ///   Critical: Called only by SecurityCritical code DynamicRendererThreadManager::ctor 
        /// 
        [SecurityCritical] 
        public static void AddListener(Dispatcher source, IWeakEventListener listener) 
        {
            CurrentManager.ProtectedAddListener(source, listener); 
        }


        #endregion Public Methods 

        #region Protected Methods 
 
        //
        //  Protected Methods 
        //

        /// 
        /// Listen to the given source for the event. 
        /// 
        protected override void StartListening(object source) 
        { 
            Dispatcher typedSource = (Dispatcher)source;
            typedSource.ShutdownStarted += new EventHandler(OnShutdownStarted); 
        }

        /// 
        /// Stop listening to the given source for the event. 
        /// 
        protected override void StopListening(object source) 
        { 
            Dispatcher typedSource = (Dispatcher)source;
            typedSource.ShutdownStarted -= new EventHandler(OnShutdownStarted); 
        }

        #endregion Protected Methods
 
        #region Private Properties
 
        // 
        //  Private Properties
        // 

        /// 
        /// get the event manager for the current thread
        ///  
        /// 
        ///   Critical: Called only by SecurityCritical code DynamicRendererThreadManager::ctor 
        ///  
        private static DispatcherShutdownStartedEventManager CurrentManager
        { 
            [SecurityCritical]
            get
            {
                Type managerType = typeof(DispatcherShutdownStartedEventManager); 
                DispatcherShutdownStartedEventManager manager = (DispatcherShutdownStartedEventManager)GetCurrentManager(managerType);
 
                // at first use, create and register a new manager 
                if (manager == null)
                { 
                    manager = new DispatcherShutdownStartedEventManager();
                    SetCurrentManager(managerType, manager);
                }
 
                return manager;
            } 
        } 

        #endregion Private Properties 

        #region Private Methods

        // 
        //  Private Methods
        // 
 
        // event handler for ShutdownStarted event
        private void OnShutdownStarted(object sender, EventArgs args) 
        {
            DeliverEvent(sender, args);
        }
 
        #endregion Private Methods
    } 
 
    /////////////////////////////////////////////////////////////////////////
    ///  
    /// This class provides a Dispatcher on a shared thread for use in real time inking.  Each
    /// instance of this class must call Dispose() in order to have this thread shut
    /// down properly.
    ///  
    internal class DynamicRendererThreadManager : IWeakEventListener, IDisposable
    { 
        [ThreadStatic] 
        private static WeakReference _tsDRTMWeakRef;
 
        internal static DynamicRendererThreadManager GetCurrentThreadInstance()
        {
            // Create the threadstatic DynamicRendererThreadManager as needed for calling thread.
            // It only creates one 
            if (_tsDRTMWeakRef == null || _tsDRTMWeakRef.Target == null)
            { 
                _tsDRTMWeakRef = new WeakReference(new DynamicRendererThreadManager()); 
            }
            return _tsDRTMWeakRef.Target as DynamicRendererThreadManager; 
        }

        private volatile Dispatcher __inkingDispatcher; // Can be accessed from multiple threads.
        private bool _disposed; 

        ///  
        /// Private contructor called by static method so that we can only ever create one of these per thread! 
        /// 
        ///  
        ///   Critical: This code creates a singleton thread that runs it own Dispatcher pump via InkingThreadProc.
        ///             Called by DynamicRenderer.CreateRealTimeVisuals().
        ///   TreatAsSafe: Calling this over and over can only create one shared thread with its own dispatcher which is at
        ///   the most a nuisance. 
        /// 
        [SecurityCritical,SecurityTreatAsSafe] 
        private DynamicRendererThreadManager() 
        {
            // Create the thread 
            DynamicRendererThreadManagerWorker worker = new DynamicRendererThreadManagerWorker();
            __inkingDispatcher = worker.StartUpAndReturnDispatcher();

            // NTRAID:WINDOWSOS#1877251-2006/10/10-WAYNEZEN, 
            // Add a weak listener to the application dispatcher's ShutdownStarted event. So we can
            // shut down our dynamic rendering thread gracefully when the app dispatcher is being shut down. 
            DispatcherShutdownStartedEventManager.AddListener(Dispatcher.CurrentDispatcher, this); 

            Debug.Assert(__inkingDispatcher != null); // We should have a valid ref here 
        }

        // Finalizer - clean up thread
        ~DynamicRendererThreadManager() 
        {
            Dispose(false); 
        } 

        ///  
        /// IDisposable.Dispose implementation.
        /// 
        public void Dispose()
        { 
            // NOTE: This object is internal to the DynamicRenderer and you really shouldn't call this.
            //   It's was added to be consistent with .NET design guidelines. 
            //   Just let the finalizer do any required clean up work! 
            Dispose(true);
            GC.SuppressFinalize(this); 
        }

        /// 
        /// Handle events from the centralized event table 
        /// 
        bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs args) 
        { 
            //NOTE: if DispatcherShutdownStartedEventManager is updated to listen
            //to anything besides ShutdownStarted, you should disambiguate the event here 
            if (managerType == typeof(DispatcherShutdownStartedEventManager))
            {
                OnAppDispatcherShutdown(sender, args);
            } 
            else
            { 
                return false;       // unrecognized event 
            }
 
            return true;
        }

 
        /// 
        /// The app dispatcher Shutdown Handler 
        ///  
        /// 
        ///  
        private void OnAppDispatcherShutdown(object sender, EventArgs e)
        {
            Dispatcher inkingDispatcher = __inkingDispatcher;
            // Return from here if the inking dispathcer is gone already. 
            if (inkingDispatcher == null)
                return; 
 
            // Mashal the Dispose call, which will shut down our Dynamic rendering thread, to the inking dispatcher.
            inkingDispatcher.Invoke(DispatcherPriority.Send, 
                (DispatcherOperationCallback)delegate(object unused)
                {
                    Dispose();
                    return null; 
                },
                null); 
        } 

        ///  
        /// Handles disposing of internal object data.
        /// 
        /// true when freeing managed and unmanaged resources; false if freeing just unmanaged resources.
        ///  
        /// Critical - Calls SecurityCritical method Dispatcher.CriticalShutdown.
        ///          Called by Dispose() and Finalizer. 
        /// TreatAsSafe -  No critical data returned or accepted as input. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        void Dispose(bool disposing)
        {
            if(!_disposed)
            { 
                _disposed = true;
 
                // Free up the thread 
                if (__inkingDispatcher != null && !Environment.HasShutdownStarted)
                { 
                    try
                    {
                        __inkingDispatcher.CriticalInvokeShutdown();
                    } 
                    catch(System.ComponentModel.Win32Exception e)
                    { 
                        if (e.NativeErrorCode != 1400) // ERROR_INVALID_WINDOW_HANDLE 
                        {
                            // This is an unlocalized string but it only prints on the Debug Console 
                            Debug.WriteLine(String.Format("Dispatcher.CriticalInvokeShutdown() Failed.  Error={0}", e.NativeErrorCode));
                        }
                    }
                    finally 
                    {
                        __inkingDispatcher = null; 
                    } 
                }
            } 
            GC.KeepAlive(this);
        }

 
        /// 
        /// Gets the inking thread dispatcher. 
        ///  
        internal Dispatcher ThreadDispatcher
        { 
            get
            {
                return __inkingDispatcher;
            } 
        }
 
 
        // Helper class to manager the thread startup and thread proc.  Needed in order to allow
        // the DynamicRendererThreadManager to get garbage collected. 
        private class DynamicRendererThreadManagerWorker
        {
            private Dispatcher _dispatcher;
            private AutoResetEvent _startupCompleted; 

            ///  
            /// Constructor. 
            /// 
            internal DynamicRendererThreadManagerWorker() 
            {
            }

            ///  
            ///   Critical: This code creates a singleton thread that runs it own Dispatcher pump via InkingThreadProc.
            ///             Called by DynamicRendererThreadManager constructor. 
            ///   the most a nuisance. 
            /// 
            [SecurityCritical] 
            internal Dispatcher StartUpAndReturnDispatcher()
            {
                _startupCompleted = new AutoResetEvent(false);
                Thread inkingThread = new Thread(new ThreadStart(InkingThreadProc)); 
                inkingThread.SetApartmentState(ApartmentState.STA);
                inkingThread.IsBackground = true; // Don't keep process alive if this thread still running. 
                inkingThread.Start(); 

                _startupCompleted.WaitOne(); 
                _startupCompleted.Close();
                _startupCompleted = null;

                return _dispatcher; 
            }
 
            ///  
            ///   Critical: This code calls into Dispatcher.Run on a given thread
            ///  
            [SecurityCritical]
            public void InkingThreadProc()
            {
                Thread.CurrentThread.Name = "DynamicRenderer"; 
                // Now make sure we create the dispatcher.
                _dispatcher = Dispatcher.CurrentDispatcher; 
                // Now we can signal that everything is set up. 
                _startupCompleted.Set();
                // Now start the dispatcher message loop for this thread. 
                Dispatcher.Run();
            }
        }
 
    }
 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// File: DynamicRendererThreadManager.cs
//
// Description: 
//      Dynamic Renderering Dispatcher - Provides shared Dispatcher for off application
//      Dispatcher inking support. 
// 
// Copyright (C) 2003-2004 by Microsoft Corporation.  All rights reserved.
// 
//---------------------------------------------------------------------------

using System;
using System.Diagnostics; 
using System.Collections.Specialized;
using System.Collections.Generic; 
using System.Windows; 
using System.Windows.Input;
using System.Windows.Media; 
using System.Threading;
using System.Windows.Threading;
using MS.Utility;
using System.Security; 
using System.Security.Permissions;
using MS.Internal; 
 
namespace System.Windows.Input.StylusPlugIns
{ 
    /// 
    /// Manager for the Dispatcher.ShutdownStarted event.
    /// 
    // Note: this class should have the same visibility (public / internal / 
    // private) as the event it manages.  If the event is not public, change
    // the visibility of this class accordingly. 
    internal sealed class DispatcherShutdownStartedEventManager : WeakEventManager 
    {
        #region Constructors 

        //
        //  Constructors
        // 

        private DispatcherShutdownStartedEventManager() 
        { 
        }
 
        #endregion Constructors

        #region Public Methods
 
        //
        //  Public Methods 
        // 

        ///  
        /// Add a listener to the given source's event.
        /// 
        /// 
        ///   Critical: Called only by SecurityCritical code DynamicRendererThreadManager::ctor 
        /// 
        [SecurityCritical] 
        public static void AddListener(Dispatcher source, IWeakEventListener listener) 
        {
            CurrentManager.ProtectedAddListener(source, listener); 
        }


        #endregion Public Methods 

        #region Protected Methods 
 
        //
        //  Protected Methods 
        //

        /// 
        /// Listen to the given source for the event. 
        /// 
        protected override void StartListening(object source) 
        { 
            Dispatcher typedSource = (Dispatcher)source;
            typedSource.ShutdownStarted += new EventHandler(OnShutdownStarted); 
        }

        /// 
        /// Stop listening to the given source for the event. 
        /// 
        protected override void StopListening(object source) 
        { 
            Dispatcher typedSource = (Dispatcher)source;
            typedSource.ShutdownStarted -= new EventHandler(OnShutdownStarted); 
        }

        #endregion Protected Methods
 
        #region Private Properties
 
        // 
        //  Private Properties
        // 

        /// 
        /// get the event manager for the current thread
        ///  
        /// 
        ///   Critical: Called only by SecurityCritical code DynamicRendererThreadManager::ctor 
        ///  
        private static DispatcherShutdownStartedEventManager CurrentManager
        { 
            [SecurityCritical]
            get
            {
                Type managerType = typeof(DispatcherShutdownStartedEventManager); 
                DispatcherShutdownStartedEventManager manager = (DispatcherShutdownStartedEventManager)GetCurrentManager(managerType);
 
                // at first use, create and register a new manager 
                if (manager == null)
                { 
                    manager = new DispatcherShutdownStartedEventManager();
                    SetCurrentManager(managerType, manager);
                }
 
                return manager;
            } 
        } 

        #endregion Private Properties 

        #region Private Methods

        // 
        //  Private Methods
        // 
 
        // event handler for ShutdownStarted event
        private void OnShutdownStarted(object sender, EventArgs args) 
        {
            DeliverEvent(sender, args);
        }
 
        #endregion Private Methods
    } 
 
    /////////////////////////////////////////////////////////////////////////
    ///  
    /// This class provides a Dispatcher on a shared thread for use in real time inking.  Each
    /// instance of this class must call Dispose() in order to have this thread shut
    /// down properly.
    ///  
    internal class DynamicRendererThreadManager : IWeakEventListener, IDisposable
    { 
        [ThreadStatic] 
        private static WeakReference _tsDRTMWeakRef;
 
        internal static DynamicRendererThreadManager GetCurrentThreadInstance()
        {
            // Create the threadstatic DynamicRendererThreadManager as needed for calling thread.
            // It only creates one 
            if (_tsDRTMWeakRef == null || _tsDRTMWeakRef.Target == null)
            { 
                _tsDRTMWeakRef = new WeakReference(new DynamicRendererThreadManager()); 
            }
            return _tsDRTMWeakRef.Target as DynamicRendererThreadManager; 
        }

        private volatile Dispatcher __inkingDispatcher; // Can be accessed from multiple threads.
        private bool _disposed; 

        ///  
        /// Private contructor called by static method so that we can only ever create one of these per thread! 
        /// 
        ///  
        ///   Critical: This code creates a singleton thread that runs it own Dispatcher pump via InkingThreadProc.
        ///             Called by DynamicRenderer.CreateRealTimeVisuals().
        ///   TreatAsSafe: Calling this over and over can only create one shared thread with its own dispatcher which is at
        ///   the most a nuisance. 
        /// 
        [SecurityCritical,SecurityTreatAsSafe] 
        private DynamicRendererThreadManager() 
        {
            // Create the thread 
            DynamicRendererThreadManagerWorker worker = new DynamicRendererThreadManagerWorker();
            __inkingDispatcher = worker.StartUpAndReturnDispatcher();

            // NTRAID:WINDOWSOS#1877251-2006/10/10-WAYNEZEN, 
            // Add a weak listener to the application dispatcher's ShutdownStarted event. So we can
            // shut down our dynamic rendering thread gracefully when the app dispatcher is being shut down. 
            DispatcherShutdownStartedEventManager.AddListener(Dispatcher.CurrentDispatcher, this); 

            Debug.Assert(__inkingDispatcher != null); // We should have a valid ref here 
        }

        // Finalizer - clean up thread
        ~DynamicRendererThreadManager() 
        {
            Dispose(false); 
        } 

        ///  
        /// IDisposable.Dispose implementation.
        /// 
        public void Dispose()
        { 
            // NOTE: This object is internal to the DynamicRenderer and you really shouldn't call this.
            //   It's was added to be consistent with .NET design guidelines. 
            //   Just let the finalizer do any required clean up work! 
            Dispose(true);
            GC.SuppressFinalize(this); 
        }

        /// 
        /// Handle events from the centralized event table 
        /// 
        bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs args) 
        { 
            //NOTE: if DispatcherShutdownStartedEventManager is updated to listen
            //to anything besides ShutdownStarted, you should disambiguate the event here 
            if (managerType == typeof(DispatcherShutdownStartedEventManager))
            {
                OnAppDispatcherShutdown(sender, args);
            } 
            else
            { 
                return false;       // unrecognized event 
            }
 
            return true;
        }

 
        /// 
        /// The app dispatcher Shutdown Handler 
        ///  
        /// 
        ///  
        private void OnAppDispatcherShutdown(object sender, EventArgs e)
        {
            Dispatcher inkingDispatcher = __inkingDispatcher;
            // Return from here if the inking dispathcer is gone already. 
            if (inkingDispatcher == null)
                return; 
 
            // Mashal the Dispose call, which will shut down our Dynamic rendering thread, to the inking dispatcher.
            inkingDispatcher.Invoke(DispatcherPriority.Send, 
                (DispatcherOperationCallback)delegate(object unused)
                {
                    Dispose();
                    return null; 
                },
                null); 
        } 

        ///  
        /// Handles disposing of internal object data.
        /// 
        /// true when freeing managed and unmanaged resources; false if freeing just unmanaged resources.
        ///  
        /// Critical - Calls SecurityCritical method Dispatcher.CriticalShutdown.
        ///          Called by Dispose() and Finalizer. 
        /// TreatAsSafe -  No critical data returned or accepted as input. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        void Dispose(bool disposing)
        {
            if(!_disposed)
            { 
                _disposed = true;
 
                // Free up the thread 
                if (__inkingDispatcher != null && !Environment.HasShutdownStarted)
                { 
                    try
                    {
                        __inkingDispatcher.CriticalInvokeShutdown();
                    } 
                    catch(System.ComponentModel.Win32Exception e)
                    { 
                        if (e.NativeErrorCode != 1400) // ERROR_INVALID_WINDOW_HANDLE 
                        {
                            // This is an unlocalized string but it only prints on the Debug Console 
                            Debug.WriteLine(String.Format("Dispatcher.CriticalInvokeShutdown() Failed.  Error={0}", e.NativeErrorCode));
                        }
                    }
                    finally 
                    {
                        __inkingDispatcher = null; 
                    } 
                }
            } 
            GC.KeepAlive(this);
        }

 
        /// 
        /// Gets the inking thread dispatcher. 
        ///  
        internal Dispatcher ThreadDispatcher
        { 
            get
            {
                return __inkingDispatcher;
            } 
        }
 
 
        // Helper class to manager the thread startup and thread proc.  Needed in order to allow
        // the DynamicRendererThreadManager to get garbage collected. 
        private class DynamicRendererThreadManagerWorker
        {
            private Dispatcher _dispatcher;
            private AutoResetEvent _startupCompleted; 

            ///  
            /// Constructor. 
            /// 
            internal DynamicRendererThreadManagerWorker() 
            {
            }

            ///  
            ///   Critical: This code creates a singleton thread that runs it own Dispatcher pump via InkingThreadProc.
            ///             Called by DynamicRendererThreadManager constructor. 
            ///   the most a nuisance. 
            /// 
            [SecurityCritical] 
            internal Dispatcher StartUpAndReturnDispatcher()
            {
                _startupCompleted = new AutoResetEvent(false);
                Thread inkingThread = new Thread(new ThreadStart(InkingThreadProc)); 
                inkingThread.SetApartmentState(ApartmentState.STA);
                inkingThread.IsBackground = true; // Don't keep process alive if this thread still running. 
                inkingThread.Start(); 

                _startupCompleted.WaitOne(); 
                _startupCompleted.Close();
                _startupCompleted = null;

                return _dispatcher; 
            }
 
            ///  
            ///   Critical: This code calls into Dispatcher.Run on a given thread
            ///  
            [SecurityCritical]
            public void InkingThreadProc()
            {
                Thread.CurrentThread.Name = "DynamicRenderer"; 
                // Now make sure we create the dispatcher.
                _dispatcher = Dispatcher.CurrentDispatcher; 
                // Now we can signal that everything is set up. 
                _startupCompleted.Set();
                // Now start the dispatcher message loop for this thread. 
                Dispatcher.Run();
            }
        }
 
    }
 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK