示例#1
0
        public Task DispatchAsync(Func <Task> func, DispatcherQueuePriority priority = DispatcherQueuePriority.Normal)
        {
            if (_dispatcher.HasThreadAccess && priority == DispatcherQueuePriority.Normal)
            {
                return(func());
            }
            else
            {
                var tcs    = new TaskCompletionSource <object>();
                var result = _dispatcher.TryEnqueue(priority, async() =>
                {
                    try
                    {
                        await func();
                        tcs.TrySetResult(null);
                    }
                    catch (Exception ex)
                    {
                        tcs.TrySetException(ex);
                    }
                });

                if (result)
                {
                    return(tcs.Task);
                }

                return(Task.CompletedTask);
            }
        }
示例#2
0
        public Task <T> DispatchAsync <T>(Func <T> func, DispatcherQueuePriority priority = DispatcherQueuePriority.Normal)
        {
            if (_dispatcher.HasThreadAccess && priority == DispatcherQueuePriority.Normal)
            {
                return(Task.FromResult(func()));
            }
            else
            {
                var tcs    = new TaskCompletionSource <T>();
                var result = _dispatcher.TryEnqueue(priority, () =>
                {
                    try
                    {
                        tcs.TrySetResult(func());
                    }
                    catch (Exception ex)
                    {
                        tcs.TrySetException(ex);
                    }
                });

                if (result)
                {
                    return(tcs.Task);
                }
                else
                {
                    return(Task.FromResult <T>(default));
示例#3
0
        public Task DispatchAsync(Action action, DispatcherQueuePriority priority = DispatcherQueuePriority.Normal)
        {
            if (ApiInfo.CanCheckThreadAccess && _dispatcher.HasThreadAccess && priority == DispatcherQueuePriority.Normal)
            {
                action();
                return(Task.CompletedTask);
            }
            else
            {
                var tcs    = new TaskCompletionSource <object>();
                var result = _dispatcher.TryEnqueue(priority, () =>
                {
                    try
                    {
                        action();
                        tcs.TrySetResult(null);
                    }
                    catch (Exception ex)
                    {
                        tcs.TrySetException(ex);
                    }
                });

                if (result)
                {
                    return(tcs.Task);
                }

                return(Task.CompletedTask);
            }
        }
示例#4
0
        bool TryEnqueueNative(DispatcherQueuePriority priority, DispatcherQueueHandler callback)
        {
            var p = priority switch
            {
                DispatcherQueuePriority.Normal => CoreDispatcherPriority.Normal,
                DispatcherQueuePriority.High => CoreDispatcherPriority.High,
                DispatcherQueuePriority.Low => CoreDispatcherPriority.Low,
                _ => CoreDispatcherPriority.Normal
            };

            CoreDispatcher.Main.RunAsync(p, () => callback());

            return(true);
        }
    }
示例#5
0
    /// <summary>
    /// Runs the specified task on the thread associated with the <see cref="DispatcherQueue"/>
    /// with the specified priority asynchronously.
    /// </summary>
    /// <typeparam name="TResult">The type of the result returned by the task.</typeparam>
    /// <param name="dispatcher">The <see cref="DispatcherQueue"/> with which the thread is associated.</param>
    /// <param name="priority">The priority of the task (such as Low, Normal, or High).</param>
    /// <param name="action">The delegate to the task to execute.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    public static Task <TResult> RunAsync <TResult>(this DispatcherQueue dispatcher, DispatcherQueuePriority priority, Func <TResult> action)
    {
        if (dispatcher.HasThreadAccess)
        {
            return(PerformDispatcherQueueAction(action));
        }

        var taskCompletionSource = new TaskCompletionSource <TResult>();

        if (!dispatcher.TryEnqueue(priority, () => PerformDispatcherQueueAction(taskCompletionSource, action)))
        {
            taskCompletionSource.SetException(new InvalidOperationException("Failed to enqueue the task to execute."));
        }

        return(taskCompletionSource.Task);
    }
            static Task TryEnqueueAsync(DispatcherQueue dispatcher, Action function, DispatcherQueuePriority priority)
            {
                var taskCompletionSource = new TaskCompletionSource <object?>();

                if (!dispatcher.TryEnqueue(priority, () =>
                {
                    try
                    {
                        function();

                        taskCompletionSource.SetResult(null);
                    }
                    catch (Exception e)
                    {
                        taskCompletionSource.SetException(e);
                    }
                }))
                {
                    taskCompletionSource.SetException(GetEnqueueException("Failed to enqueue the operation"));
                }

                return(taskCompletionSource.Task);
            }
 /// <summary>
 /// Constructs a <see cref="DispatcherScheduler"/> that schedules units of work on the given <see cref="Microsoft.UI.Dispatching.DispatcherQueue"/> at the given priority.
 /// </summary>
 /// <param name="dispatcherQueue"><see cref="Microsoft.UI.Dispatching.DispatcherQueue"/> to schedule work on.</param>
 /// <param name="priority">Priority at which units of work are scheduled.</param>
 /// <exception cref="ArgumentNullException"><paramref name="dispatcherQueue"/> is <c>null</c>.</exception>
 public DispatcherQueueScheduler(DispatcherQueue dispatcherQueue, DispatcherQueuePriority priority)
 {
     DispatcherQueue = dispatcherQueue ?? throw new ArgumentNullException(nameof(dispatcherQueue));
     Priority        = priority;
 }
        /// <summary>
        /// Extension method for <see cref="DispatcherQueue"/>. Offering an actual awaitable <see cref="Task{T}"/> with optional result that will be executed on the given dispatcher.
        /// </summary>
        /// <typeparam name="T">Returned data type of the function.</typeparam>
        /// <param name="dispatcher">DispatcherQueue of a thread to run <paramref name="function"/>.</param>
        /// <param name="function"> Function to be executed on the given dispatcher.</param>
        /// <param name="priority">DispatcherQueue execution priority, default is normal.</param>
        /// <returns>An awaitable <see cref="Task{T}"/> for the operation.</returns>
        /// <remarks>If the current thread has UI access, <paramref name="function"/> will be invoked directly.</remarks>
        public static Task <T> ExecuteOnUIThreadAsync <T>(this DispatcherQueue dispatcher, Func <T> function, DispatcherQueuePriority priority = DispatcherQueuePriority.Normal)
        {
            if (function is null)
            {
                throw new ArgumentNullException(nameof(function));
            }

            // Skip the dispatch, if possible
            // Ignoring for now, but need to map the CurrentThreadID for all dispatcher queue code we have

            /*
             * if (dispatcher.HasThreadAccess)
             * {
             *  try
             *  {
             *      return Task.FromResult(function());
             *  }
             *  catch (Exception e)
             *  {
             *      return Task.FromException<T>(e);
             *  }
             * }
             */

            var taskCompletionSource = new TaskCompletionSource <T>();

            _ = dispatcher?.TryEnqueue(priority, () =>
            {
                try
                {
                    taskCompletionSource.SetResult(function());
                }
                catch (Exception e)
                {
                    taskCompletionSource.SetException(e);
                }
            });

            return(taskCompletionSource.Task);
        }
        /// <summary>
        /// Extension method for <see cref="DispatcherQueue"/>. Offering an actual awaitable <see cref="Task"/> with optional result that will be executed on the given dispatcher.
        /// </summary>
        /// <param name="dispatcher">DispatcherQueue of a thread to run <paramref name="function"/>.</param>
        /// <param name="function"> Function to be executed on the given dispatcher.</param>
        /// <param name="priority">DispatcherQueue execution priority, default is normal.</param>
        /// <returns>An awaitable <see cref="Task"/> for the operation.</returns>
        /// <remarks>If the current thread has UI access, <paramref name="function"/> will be invoked directly.</remarks>
        public static Task ExecuteOnUIThreadAsync(this DispatcherQueue dispatcher, Action function, DispatcherQueuePriority priority = DispatcherQueuePriority.Normal)
        {
            if (function is null)
            {
                throw new ArgumentNullException(nameof(function));
            }

            /* Run the function directly when we have thread access.
             * Also reuse Task.CompletedTask in case of success,
             * to skip an unnecessary heap allocation for every invocation. */

            // Ignoring for now, but need to map the CurrentThreadID for all dispatcher queue code we have

            /*
             * if (dispatcher.HasThreadAccess)
             * {
             *  try
             *  {
             *      function();
             *
             *      return Task.CompletedTask;
             *  }
             *  catch (Exception e)
             *  {
             *      return Task.FromException(e);
             *  }
             * }
             */

            var taskCompletionSource = new TaskCompletionSource <object>();

            _ = dispatcher?.TryEnqueue(priority, () =>
            {
                try
                {
                    function();

                    taskCompletionSource.SetResult(null);
                }
                catch (Exception e)
                {
                    taskCompletionSource.SetException(e);
                }
            });

            return(taskCompletionSource.Task);
        }
        /// <summary>
        /// Extension method for <see cref="DispatcherQueue"/>. Offering an actual awaitable <see cref="Task"/> with optional result that will be executed on the given dispatcher.
        /// </summary>
        /// <param name="dispatcher">DispatcherQueue of a thread to run <paramref name="function"/>.</param>
        /// <param name="function">Asynchronous function to be executed on the given dispatcher.</param>
        /// <param name="priority">DispatcherQueue execution priority, default is normal.</param>
        /// <returns>An awaitable <see cref="Task"/> for the operation.</returns>
        /// <remarks>If the current thread has UI access, <paramref name="function"/> will be invoked directly.</remarks>
        public static Task ExecuteOnUIThreadAsync(this DispatcherQueue dispatcher, Func <Task> function, DispatcherQueuePriority priority = DispatcherQueuePriority.Normal)
        {
            if (function is null)
            {
                throw new ArgumentNullException(nameof(function));
            }

            /* If we have thread access, we can retrieve the task directly.
             * We don't use ConfigureAwait(false) in this case, in order
             * to let the caller continue its execution on the same thread
             * after awaiting the task returned by this function. */

            // Ignoring for now, but need to map the CurrentThreadID for all dispatcher queue code we have

            /*
             * if (dispatcher.HasThreadAccess)
             * {
             *  try
             *  {
             *      if (function() is Task awaitableResult)
             *      {
             *          return awaitableResult;
             *      }
             *
             *      return Task.FromException(new InvalidOperationException("The Task returned by function cannot be null."));
             *  }
             *  catch (Exception e)
             *  {
             *      return Task.FromException(e);
             *  }
             * }
             */

            var taskCompletionSource = new TaskCompletionSource <object>();

            _ = dispatcher?.TryEnqueue(priority, async() =>
            {
                try
                {
                    if (function() is Task awaitableResult)
                    {
                        await awaitableResult.ConfigureAwait(false);

                        taskCompletionSource.SetResult(null);
                    }
                    else
                    {
                        taskCompletionSource.SetException(new InvalidOperationException("The Task returned by function cannot be null."));
                    }
                }
                catch (Exception e)
                {
                    taskCompletionSource.SetException(e);
                }
            });
        /// <summary>
        /// Extension method for <see cref="DispatcherQueue"/>. Offering an actual awaitable <see cref="Task{T}"/> with optional result that will be executed on the given dispatcher.
        /// </summary>
        /// <typeparam name="T">Returned data type of the function.</typeparam>
        /// <param name="dispatcher">DispatcherQueue of a thread to run <paramref name="function"/>.</param>
        /// <param name="function"> Function to be executed on the given dispatcher.</param>
        /// <param name="priority">DispatcherQueue execution priority, default is normal.</param>
        /// <returns>An awaitable <see cref="Task{T}"/> for the operation.</returns>
        /// <remarks>If the current thread has UI access, <paramref name="function"/> will be invoked directly.</remarks>
        public static Task <T> ExecuteOnUIThreadAsync <T>(this DispatcherQueue dispatcher, Func <T> function, DispatcherQueuePriority priority = DispatcherQueuePriority.Normal)
        {
            if (function is null)
            {
                throw new ArgumentNullException(nameof(function));
            }

            if (HasThreadAccess(dispatcher))
            {
                try
                {
                    return(Task.FromResult(function()));
                }
                catch (Exception e)
                {
                    return(Task.FromException <T>(e));
                }
            }

            var taskCompletionSource = new TaskCompletionSource <T>();

            _ = dispatcher.TryEnqueue(priority, () =>
            {
                try
                {
                    taskCompletionSource.SetResult(function());
                }
                catch (Exception e)
                {
                    taskCompletionSource.SetException(e);
                }
            });

            return(taskCompletionSource.Task);
        }
        /// <summary>
        /// Extension method for <see cref="DispatcherQueue"/>. Offering an actual awaitable <see cref="Task"/> with optional result that will be executed on the given dispatcher.
        /// </summary>
        /// <param name="dispatcher">DispatcherQueue of a thread to run <paramref name="function"/>.</param>
        /// <param name="function"> Function to be executed on the given dispatcher.</param>
        /// <param name="priority">DispatcherQueue execution priority, default is normal.</param>
        /// <returns>An awaitable <see cref="Task"/> for the operation.</returns>
        /// <remarks>If the current thread has UI access, <paramref name="function"/> will be invoked directly.</remarks>
        public static Task ExecuteOnUIThreadAsync(this DispatcherQueue dispatcher, Action function, DispatcherQueuePriority priority = DispatcherQueuePriority.Normal)
        {
            if (function is null)
            {
                throw new ArgumentNullException(nameof(function));
            }

            /* Run the function directly when we have thread access.
             * Also reuse Task.CompletedTask in case of success,
             * to skip an unnecessary heap allocation for every invocation. */
            if (HasThreadAccess(dispatcher))
            {
                try
                {
                    function();

                    return(Task.CompletedTask);
                }
                catch (Exception e)
                {
                    return(Task.FromException(e));
                }
            }

            var taskCompletionSource = new TaskCompletionSource <object>();

            _ = dispatcher.TryEnqueue(priority, () =>
            {
                try
                {
                    function();

                    taskCompletionSource.SetResult(null);
                }
                catch (Exception e)
                {
                    taskCompletionSource.SetException(e);
                }
            });

            return(taskCompletionSource.Task);
        }
 bool TryEnqueueNative(DispatcherQueuePriority priority, DispatcherQueueHandler callback)
 {
     throw new NotSupportedException();
 }
示例#14
0
 bool TryEnqueueNative(DispatcherQueuePriority priority, DispatcherQueueHandler callback)
 {
     return(EnqueueNativeOverride(priority, callback));
 }
        public static Task EnqueueAsync(this DispatcherQueue dispatcher, Action function, DispatcherQueuePriority priority = DispatcherQueuePriority.Normal)
        {
            // Run the function directly when we have thread access.
            // Also reuse Task.CompletedTask in case of success,
            // to skip an unnecessary heap allocation for every invocation.
            if (IsHasThreadAccessPropertyAvailable && dispatcher.HasThreadAccess)
            {
                try
                {
                    function();

                    return(Task.CompletedTask);
                }
                catch (Exception e)
                {
                    return(Task.FromException(e));
                }
            }