Skip to content

Commit

Permalink
ThreadSwitcher 新增 SynchronizationContextThreadSwitcher
Browse files Browse the repository at this point in the history
  • Loading branch information
wherewhere committed Mar 11, 2024
1 parent 8db6284 commit a82f877
Showing 1 changed file with 57 additions and 28 deletions.
85 changes: 57 additions & 28 deletions CoreAppUWP/Common/ThreadSwitcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ public interface IThreadSwitcher : INotifyCompletion
/// <summary>
/// Gets a value that indicates whether the asynchronous operation has completed.
/// </summary>
bool IsCompleted => true;
bool IsCompleted { get; }

/// <summary>
/// Ends the await on the completed task.
/// </summary>
void GetResult() { }
void GetResult();

/// <summary>
/// Gets an awaiter used to await this <see cref="IThreadSwitcher"/>.
Expand All @@ -31,33 +31,41 @@ void GetResult() { }
IThreadSwitcher GetAwaiter();
}

/// <summary>
/// The interface of helper type for switch thread.
/// </summary>
/// <typeparam name="T">The type of the result of <see cref="GetAwaiter"/>.</typeparam>
public interface IThreadSwitcher<T> : IThreadSwitcher
{
/// <summary>
/// Gets an awaiter used to await <see cref="T"/>.
/// </summary>
/// <returns>An awaiter instance.</returns>
new T GetAwaiter();
}

/// <summary>
/// A helper type for switch thread by <see cref="CoreDispatcher"/>. This type is not intended to be used directly from your code.
/// </summary>
/// <param name="Dispatcher">A <see cref="CoreDispatcher"/> whose foreground thread to switch execution to.</param>
/// <param name="Priority">Specifies the priority for event dispatch.</param>
[EditorBrowsable(EditorBrowsableState.Never)]
public readonly record struct CoreDispatcherThreadSwitcher(CoreDispatcher Dispatcher, CoreDispatcherPriority Priority = CoreDispatcherPriority.Normal) : IThreadSwitcher
public readonly record struct CoreDispatcherThreadSwitcher(CoreDispatcher Dispatcher, CoreDispatcherPriority Priority = CoreDispatcherPriority.Normal) : IThreadSwitcher<CoreDispatcherThreadSwitcher>
{
/// <summary>
/// Gets a value that indicates whether the asynchronous operation has completed.
/// </summary>
/// <inheritdoc/>
public bool IsCompleted => Dispatcher?.HasThreadAccess != false;

/// <inheritdoc/>
public void GetResult() { }

/// <summary>
/// Gets an awaiter used to await this <see cref="CoreDispatcherThreadSwitcher"/>.
/// </summary>
/// <returns>An awaiter instance.</returns>
/// <inheritdoc/>
public CoreDispatcherThreadSwitcher GetAwaiter() => this;

/// <inheritdoc/>
IThreadSwitcher IThreadSwitcher.GetAwaiter() => this;

/// <inheritdoc/>
public void OnCompleted(Action continuation) => _ = Dispatcher?.RunAsync(Priority, () => continuation());
public void OnCompleted(Action continuation) => _ = Dispatcher.RunAsync(Priority, () => continuation());
}

/// <summary>
Expand All @@ -66,48 +74,62 @@ public void GetResult() { }
/// <param name="Dispatcher">A <see cref="DispatcherQueue"/> whose foreground thread to switch execution to.</param>
/// <param name="Priority">Specifies the priority for event dispatch.</param>
[EditorBrowsable(EditorBrowsableState.Never)]
public readonly record struct DispatcherQueueThreadSwitcher(DispatcherQueue Dispatcher, DispatcherQueuePriority Priority = DispatcherQueuePriority.Normal) : IThreadSwitcher
public readonly record struct DispatcherQueueThreadSwitcher(DispatcherQueue Dispatcher, DispatcherQueuePriority Priority = DispatcherQueuePriority.Normal) : IThreadSwitcher<DispatcherQueueThreadSwitcher>
{
/// <summary>
/// Gets a value that indicates whether the asynchronous operation has completed.
/// </summary>
/// <inheritdoc/>
public bool IsCompleted => Dispatcher?.HasThreadAccess != false;

/// <inheritdoc/>
public void GetResult() { }

/// <summary>
/// Gets an awaiter used to await this <see cref="DispatcherQueueThreadSwitcher"/>.
/// </summary>
/// <returns>An awaiter instance.</returns>
/// <inheritdoc/>
public DispatcherQueueThreadSwitcher GetAwaiter() => this;

/// <inheritdoc/>
IThreadSwitcher IThreadSwitcher.GetAwaiter() => this;

/// <inheritdoc/>
public void OnCompleted(Action continuation) => _ = Dispatcher?.TryEnqueue(Priority, () => continuation());
public void OnCompleted(Action continuation) => _ = Dispatcher.TryEnqueue(Priority, () => continuation());
}

/// <summary>
/// A helper type for switch thread by <see cref="SynchronizationContext"/>. This type is not intended to be used directly from your code.
/// </summary>
/// <param name="Context">A <see cref="SynchronizationContext"/> whose foreground thread to switch execution to.</param>
[EditorBrowsable(EditorBrowsableState.Never)]
public readonly record struct SynchronizationContextThreadSwitcher(SynchronizationContext Context) : IThreadSwitcher<SynchronizationContextThreadSwitcher>
{
/// <inheritdoc/>
public bool IsCompleted => Context is not SynchronizationContext context
|| SynchronizationContext.Current == context;

/// <inheritdoc/>
public void GetResult() { }

/// <inheritdoc/>
public SynchronizationContextThreadSwitcher GetAwaiter() => this;

/// <inheritdoc/>
IThreadSwitcher IThreadSwitcher.GetAwaiter() => this;

/// <inheritdoc/>
public void OnCompleted(Action continuation) => Context.Post(_ => continuation(), null);
}

/// <summary>
/// A helper type for switch thread by <see cref="ThreadPool"/>. This type is not intended to be used directly from your code.
/// </summary>
/// <param name="Priority">Specifies the priority for event dispatch.</param>
[EditorBrowsable(EditorBrowsableState.Never)]
public readonly record struct ThreadPoolThreadSwitcher(WorkItemPriority Priority = WorkItemPriority.Normal) : IThreadSwitcher
public readonly record struct ThreadPoolThreadSwitcher(WorkItemPriority Priority = WorkItemPriority.Normal) : IThreadSwitcher<ThreadPoolThreadSwitcher>
{
/// <summary>
/// Gets a value that indicates whether the asynchronous operation has completed.
/// </summary>
/// <inheritdoc/>
public bool IsCompleted => SynchronizationContext.Current == null;

/// <inheritdoc/>
public void GetResult() { }

/// <summary>
/// Gets an awaiter used to await this <see cref="ThreadPoolThreadSwitcher"/>.
/// </summary>
/// <returns>An awaiter instance.</returns>
/// <inheritdoc/>
public ThreadPoolThreadSwitcher GetAwaiter() => this;

/// <inheritdoc/>
Expand Down Expand Up @@ -138,6 +160,13 @@ public static class ThreadSwitcher
/// <returns>An object that you can <see langword="await"/>.</returns>
public static CoreDispatcherThreadSwitcher ResumeForegroundAsync(this CoreDispatcher dispatcher, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal) => new(dispatcher, priority);

/// <summary>
/// A helper function—for use within a coroutine—that you can <see langword="await"/> to switch execution to a specific foreground thread.
/// </summary>
/// <param name="context">A <see cref="SynchronizationContext"/> whose foreground thread to switch execution to.</param>
/// <returns>An object that you can <see langword="await"/>.</returns>
public static SynchronizationContextThreadSwitcher ResumeForegroundAsync(this SynchronizationContext context) => new(context);

/// <summary>
/// A helper function—for use within a coroutine—that returns control to the caller, and then immediately resumes execution on a thread pool thread.
/// </summary>
Expand Down

0 comments on commit a82f877

Please sign in to comment.