summaryrefslogtreecommitdiffstats
path: root/win/CS/HandBrake.ApplicationServices/Utilities/Execute.cs
blob: c98140977c0f35566a348bca7a5ef011112f8bcd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// --------------------------------------------------------------------------------------------------------------------
// <copyright company="HandBrake Project (http://handbrake.fr)" file="Execute.cs">
//   This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
// </copyright>
// <summary>
//   Enables easy marshalling of code to the UI thread.
//   Borrowed from Caliburn Micro.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace HandBrake.ApplicationServices.Utilities
{
    using System;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Threading;

    /// <summary>
    /// Enables easy marshalling of code to the UI thread.
    /// </summary>
    public static class Execute
    {
        private static System.Action<System.Action> executor = (System.Action<System.Action>)(action => action());
        private static Dispatcher dispatcher;
        private static bool? inDesignMode;

        /// <summary>
        /// Gets a value indicating whether or not the framework is in design-time mode.
        /// </summary>
        public static bool InDesignMode
        {
            get
            {
                if (!Execute.inDesignMode.HasValue)
                {
                    Execute.inDesignMode = new bool?((bool)DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty, typeof(FrameworkElement)).Metadata.DefaultValue);
                    if (!Execute.inDesignMode.GetValueOrDefault(false) && Process.GetCurrentProcess().ProcessName.StartsWith("devenv", StringComparison.Ordinal))
                        Execute.inDesignMode = new bool?(true);
                }
                return Execute.inDesignMode.GetValueOrDefault(false);
            }
        }

        /// <summary>
        /// Initializes the framework using the current dispatcher.
        /// </summary>
        public static void InitializeWithDispatcher()
        {
            Execute.dispatcher = Dispatcher.CurrentDispatcher;
            Execute.executor = (System.Action<System.Action>)null;
        }

        /// <summary>
        /// Resets the executor to use a non-dispatcher-based action executor.
        /// </summary>
        public static void ResetWithoutDispatcher()
        {
            executor = (System.Action<System.Action>)(action => action());
            dispatcher = (Dispatcher)null;
        }

        /// <summary>
        /// Sets a custom UI thread marshaller.
        /// </summary>
        /// <param name="marshaller">The marshaller.</param>
        [Obsolete]
        public static void SetUIThreadMarshaller(System.Action<System.Action> marshaller)
        {
            Execute.executor = marshaller;
            Execute.dispatcher = (Dispatcher)null;
        }

        /// <summary>
        /// The validate dispatcher.
        /// </summary>
        /// <exception cref="InvalidOperationException">
        /// Not initialized with dispatcher.
        /// </exception>
        private static void ValidateDispatcher()
        {
            if (Execute.dispatcher == null)
                throw new InvalidOperationException("Not initialized with dispatcher.");
        }

        /// <summary>
        /// Executes the action on the UI thread asynchronously.
        /// </summary>
        /// <param name="action">The action to execute.</param>
        public static void BeginOnUIThread(this System.Action action)
        {
            Execute.ValidateDispatcher();
            Execute.dispatcher.BeginInvoke((Delegate)action);
        }

        /// <summary>
        /// Executes the action on the UI thread asynchronously.
        /// </summary>
        /// <param name="action">
        /// The action to execute.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        public static Task OnUIThreadAsync(this System.Action action)
        {
            Execute.ValidateDispatcher();
            TaskCompletionSource<object> taskSource = new TaskCompletionSource<object>();
            System.Action action1 = (System.Action)(() =>
            {
                try
                {
                    action();
                    taskSource.SetResult((object)null);
                }
                catch (Exception ex)
                {
                    taskSource.SetException(ex);
                }
            });
            Execute.dispatcher.BeginInvoke((Delegate)action1);
            return (Task)taskSource.Task;
        }

        /// <summary>
        /// The check access.
        /// </summary>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        private static bool CheckAccess()
        {
            if (Execute.dispatcher != null)
                return Execute.dispatcher.CheckAccess();
            return true;
        }

        /// <summary>
        /// Executes the action on the UI thread.
        /// </summary>
        /// <param name="action">The action to execute.</param>
        public static void OnUIThread(this System.Action action)
        {
            if (Execute.executor != null)
                Execute.executor(action);
            else if (Execute.CheckAccess())
                action();
            else
                Execute.OnUIThreadAsync(action).Wait();
        }
    }
}