1: // (c) Copyright Microsoft Corporation.
2: // This source is subject to the Microsoft Public License (Ms-PL).
3: // Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
4: // All other rights reserved.
5:
6: using System.ComponentModel;
7:
8: namespace System.Windows.Threading
9: {
10: /// <summary>
11: /// A smart dispatcher system for routing actions to the user interface
12: /// thread.
13: /// </summary>
14: public static class DispatchHelper
15: {
16: /// <summary>
17: /// A single Dispatcher instance to marshall actions to the user
18: /// interface thread.
19: /// </summary>
20: private static Dispatcher _instance;
21:
22: /// <summary>
23: /// Backing field for a value indicating whether this is a design-time
24: /// environment.
25: /// </summary>
26: private static bool? _designer;
27:
28: /// <summary>
29: /// Requires an instance and attempts to find a Dispatcher if one has
30: /// not yet been set.
31: /// </summary>
32: private static void RequireInstance()
33: {
34: if (_designer == null)
35: {
36: _designer = DesignerProperties.IsInDesignTool;
37: }
38:
39: // Design-time is more of a no-op, won't be able to resolve the
40: // dispatcher if it isn't already set in these situations.
41: if (_designer == true)
42: {
43: return;
44: }
45: // Attempt to use the RootVisual of the plugin to retrieve a
46: // dispatcher instance. This call will only succeed if the current
47: // thread is the UI thread.
48: try
49: {
50: _instance = Application.Current.RootVisual.Dispatcher;
51: }
52: catch (Exception e)
53: {
54: _instance = Deployment.Current.Dispatcher;
55: }
56: if (_instance == null)
57: {
58: _instance = Deployment.Current.Dispatcher;
59: }
60: }
61:
62: /// <summary>
63: /// Initializes the SmartDispatcher system, attempting to use the
64: /// RootVisual of the plugin to retrieve a Dispatcher instance.
65: /// </summary>
66: public static void Initialize()
67: {
68: if (_instance == null)
69: {
70: RequireInstance();
71: }
72: }
73:
74: /// <summary>
75: /// Initializes the SmartDispatcher system with the dispatcher
76: /// instance.
77: /// </summary>
78: /// <param name="dispatcher">The dispatcher instance.</param>
79: public static void Initialize(Dispatcher dispatcher)
80: {
81: if (dispatcher == null)
82: {
83: throw new ArgumentNullException("dispatcher");
84: }
85:
86: _instance = dispatcher;
87:
88: if (_designer == null)
89: {
90: _designer = DesignerProperties.IsInDesignTool;
91: }
92: }
93:
94: /// <summary>
95: ///
96: /// </summary>
97: /// <returns></returns>
98: public static bool CheckAccess()
99: {
100: if (_instance == null)
101: {
102: RequireInstance();
103: }
104:
105: return _instance.CheckAccess();
106: }
107:
108: /// <summary>
109: /// Executes the specified delegate asynchronously on the user interface
110: /// thread. If the current thread is the user interface thread, the
111: /// dispatcher if not used and the operation happens immediately.
112: /// </summary>
113: /// <param name="a">A delegate to a method that takes no arguments and
114: /// does not return a value, which is either pushed onto the Dispatcher
115: /// event queue or immediately run, depending on the current thread.</param>
116: public static void BeginInvoke(Action a)
117: {
118: if (_instance == null)
119: {
120: RequireInstance();
121: }
122:
123: // If the current thread is the user interface thread, skip the
124: // dispatcher and directly invoke the Action.
125: if (_instance.CheckAccess() || _designer == true)
126: {
127: a();
128: }
129: else
130: {
131: _instance.BeginInvoke(a);
132: }
133: }
134: }
135: }