DynamicRendererThreadManager.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / System / Windows / Input / Stylus / DynamicRendererThreadManager.cs / 1305600 / 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) 
        {
            if (source == null) 
                throw new ArgumentNullException("source");
            if (listener == null)
                throw new ArgumentNullException("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