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); } }
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));
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); } }
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); } }
/// <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(); }
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)); } }