Understanding the Silverlight Dispatcher

后端 未结 2 390
无人及你
无人及你 2020-12-14 01:32

I had a Invalid Cross Thread access issue, but a little research and I managed to fix it by using the Dispatcher.

Now in my app I have objects with lazy loading. I\'

2条回答
  •  一生所求
    2020-12-14 02:08

    Ideally, store a single instance of Dispatcher that you can use elsewhere without having the thread check on it.

    Calling any singleton .Current instance may in fact cause a cross-thread access check to be invoked. By storing it first, you can avoid this to actually get the shared instance.

    I use a "SmartDispatcher" that uses a dispatcher when called off-thread, and just invokes otherwise. It solves this sort of issue.

    Post: http://www.jeff.wilcox.name/2010/04/propertychangedbase-crossthread/

    Code:

    // (c) Copyright Microsoft Corporation.
    // This source is subject to the Microsoft Public License (Ms-PL).
    // Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
    // All other rights reserved.
    
    using System.ComponentModel;
    
    namespace System.Windows.Threading
    {
        /// 
        /// A smart dispatcher system for routing actions to the user interface
        /// thread.
        /// 
        public static class SmartDispatcher
        {
            /// 
            /// A single Dispatcher instance to marshall actions to the user
            /// interface thread.
            /// 
            private static Dispatcher _instance;
    
            /// 
            /// Backing field for a value indicating whether this is a design-time
            /// environment.
            /// 
            private static bool? _designer;
    
            /// 
            /// Requires an instance and attempts to find a Dispatcher if one has
            /// not yet been set.
            /// 
            private static void RequireInstance()
            {
                if (_designer == null)
                {
                    _designer = DesignerProperties.IsInDesignTool;
                }
    
                // Design-time is more of a no-op, won't be able to resolve the
                // dispatcher if it isn't already set in these situations.
                if (_designer == true)
                {
                    return;
                }
    
                // Attempt to use the RootVisual of the plugin to retrieve a
                // dispatcher instance. This call will only succeed if the current
                // thread is the UI thread.
                try
                {
                    _instance = Application.Current.RootVisual.Dispatcher;
                }
                catch (Exception e)
                {
                    throw new InvalidOperationException("The first time SmartDispatcher is used must be from a user interface thread. Consider having the application call Initialize, with or without an instance.", e);
                }
    
                if (_instance == null)
                {
                    throw new InvalidOperationException("Unable to find a suitable Dispatcher instance.");
                }
            }
    
            /// 
            /// Initializes the SmartDispatcher system, attempting to use the
            /// RootVisual of the plugin to retrieve a Dispatcher instance.
            /// 
            public static void Initialize()
            {
                if (_instance == null)
                {
                    RequireInstance();
                }
            }
    
            /// 
            /// Initializes the SmartDispatcher system with the dispatcher
            /// instance.
            /// 
            /// The dispatcher instance.
            public static void Initialize(Dispatcher dispatcher)
            {
                if (dispatcher == null)
                {
                    throw new ArgumentNullException("dispatcher");
                }
    
                _instance = dispatcher;
    
                if (_designer == null)
                {
                    _designer = DesignerProperties.IsInDesignTool;
                }
            }
    
            /// 
            /// 
            /// 
            /// 
            public static bool CheckAccess()
            {
                if (_instance == null)
                {
                    RequireInstance();
                }
    
                return _instance.CheckAccess();
            }
    
            /// 
            /// Executes the specified delegate asynchronously on the user interface
            /// thread. If the current thread is the user interface thread, the
            /// dispatcher if not used and the operation happens immediately.
            /// 
            /// A delegate to a method that takes no arguments and 
            /// does not return a value, which is either pushed onto the Dispatcher 
            /// event queue or immediately run, depending on the current thread.
            public static void BeginInvoke(Action a)
            {
                if (_instance == null)
                {
                    RequireInstance();
                }
    
                // If the current thread is the user interface thread, skip the
                // dispatcher and directly invoke the Action.
                if (_instance.CheckAccess() || _designer == true)
                {
                    a();
                }
                else
                {
                    _instance.BeginInvoke(a);
                }
            }
        }
    }
    

提交回复
热议问题