-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
69b94d6
commit 78a1be0
Showing
20 changed files
with
974 additions
and
341 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
|
||
namespace MicaDemo.Common | ||
{ | ||
public static class Enumerable | ||
{ | ||
/// <summary> | ||
/// Performs the specified action on each element of the <see cref="IEnumerable{T}"/>. | ||
/// </summary> | ||
/// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam> | ||
/// <param name="source"></param> | ||
/// <param name="action">The <see cref="Action{T}"/> delegate to perform on each element of the <see cref="List{T}"/>.</param> | ||
/// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="action"/> is null.</exception> | ||
public static void ForEach<TSource>(this IEnumerable<TSource> source, Action<TSource> action) | ||
{ | ||
if (source == null) | ||
{ | ||
throw new ArgumentNullException(nameof(source)); | ||
} | ||
|
||
if (action == null) | ||
{ | ||
throw new ArgumentNullException(nameof(action)); | ||
} | ||
|
||
if (source is List<TSource> list) | ||
{ | ||
list.ForEach(action); | ||
} | ||
else if (source is ImmutableList<TSource> immutableList) | ||
{ | ||
immutableList.ForEach(action); | ||
} | ||
else | ||
{ | ||
foreach (TSource item in source) | ||
{ | ||
action(item); | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
using System; | ||
using System.ComponentModel; | ||
using System.Runtime.CompilerServices; | ||
using System.Threading; | ||
using Windows.Foundation.Metadata; | ||
using Windows.System; | ||
using Windows.System.Threading; | ||
using Windows.UI.Core; | ||
|
||
namespace MicaDemo.Common | ||
{ | ||
/// <summary> | ||
/// The interface of helper type for switch thread. | ||
/// </summary> | ||
public interface IThreadSwitcher : INotifyCompletion | ||
{ | ||
/// <summary> | ||
/// Gets a value that indicates whether the asynchronous operation has completed. | ||
/// </summary> | ||
bool IsCompleted { get; } | ||
|
||
/// <summary> | ||
/// Ends the await on the completed task. | ||
/// </summary> | ||
void GetResult(); | ||
|
||
/// <summary> | ||
/// Gets an awaiter used to await this <see cref="IThreadSwitcher"/>. | ||
/// </summary> | ||
/// <returns>An awaiter instance.</returns> | ||
IThreadSwitcher 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> | ||
[EditorBrowsable(EditorBrowsableState.Never)] | ||
public readonly struct CoreDispatcherThreadSwitcher : IThreadSwitcher | ||
{ | ||
private readonly CoreDispatcher dispatcher; | ||
private readonly CoreDispatcherPriority priority; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="CoreDispatcherThreadSwitcher"/> struct. | ||
/// </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> | ||
public CoreDispatcherThreadSwitcher(CoreDispatcher dispatcher, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal) | ||
{ | ||
this.dispatcher = dispatcher; | ||
this.priority = priority; | ||
} | ||
|
||
/// <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> | ||
public CoreDispatcherThreadSwitcher GetAwaiter() => this; | ||
|
||
/// <inheritdoc/> | ||
IThreadSwitcher IThreadSwitcher.GetAwaiter() => this; | ||
|
||
/// <inheritdoc/> | ||
public void OnCompleted(Action continuation) => _ = dispatcher.RunAsync(priority, () => continuation()); | ||
} | ||
|
||
/// <summary> | ||
/// A helper type for switch thread by <see cref="DispatcherQueue"/>. This type is not intended to be used directly from your code. | ||
/// </summary> | ||
[EditorBrowsable(EditorBrowsableState.Never)] | ||
public readonly struct DispatcherQueueThreadSwitcher : IThreadSwitcher | ||
{ | ||
private readonly DispatcherQueue dispatcher; | ||
private readonly DispatcherQueuePriority priority; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="DispatcherQueueThreadSwitcher"/> struct. | ||
/// </summary> | ||
/// <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> | ||
public DispatcherQueueThreadSwitcher(DispatcherQueue dispatcher, DispatcherQueuePriority priority = DispatcherQueuePriority.Normal) | ||
{ | ||
this.dispatcher = dispatcher; | ||
this.priority = priority; | ||
} | ||
|
||
/// <inheritdoc/> | ||
public bool IsCompleted => !(this.dispatcher is DispatcherQueue dispatcher) | ||
|| (ThreadSwitcher.IsHasThreadAccessPropertyAvailable && dispatcher.HasThreadAccess); | ||
|
||
/// <inheritdoc/> | ||
public void GetResult() { } | ||
|
||
/// <summary> | ||
/// Gets an awaiter used to await this <see cref="DispatcherQueueThreadSwitcher"/>. | ||
/// </summary> | ||
/// <returns>An awaiter instance.</returns> | ||
public DispatcherQueueThreadSwitcher GetAwaiter() => this; | ||
|
||
/// <inheritdoc/> | ||
IThreadSwitcher IThreadSwitcher.GetAwaiter() => this; | ||
|
||
/// <inheritdoc/> | ||
public void OnCompleted(Action continuation) => _ = dispatcher.TryEnqueue(priority, () => continuation()); | ||
} | ||
|
||
/// <summary> | ||
/// A helper type for switch thread by <see cref="ThreadPool"/>. This type is not intended to be used directly from your code. | ||
/// </summary> | ||
[EditorBrowsable(EditorBrowsableState.Never)] | ||
public readonly struct ThreadPoolThreadSwitcher : IThreadSwitcher | ||
{ | ||
private readonly WorkItemPriority priority; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="ThreadPoolThreadSwitcher"/> struct. | ||
/// </summary> | ||
/// <param name="priority">Specifies the priority for event dispatch.</param> | ||
public ThreadPoolThreadSwitcher(WorkItemPriority priority = WorkItemPriority.Normal) => this.priority = priority; | ||
|
||
/// <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> | ||
public ThreadPoolThreadSwitcher GetAwaiter() => this; | ||
|
||
/// <inheritdoc/> | ||
IThreadSwitcher IThreadSwitcher.GetAwaiter() => this; | ||
|
||
/// <inheritdoc/> | ||
public void OnCompleted(Action continuation) => _ = ThreadPool.RunAsync(_ => continuation(), priority); | ||
} | ||
|
||
/// <summary> | ||
/// The extensions for switching threads. | ||
/// </summary> | ||
public static class ThreadSwitcher | ||
{ | ||
/// <summary> | ||
/// Gets is <see cref="DispatcherQueue.HasThreadAccess"/> supported. | ||
/// </summary> | ||
public static bool IsHasThreadAccessPropertyAvailable { get; } = ApiInformation.IsMethodPresent("Windows.System.DispatcherQueue", "HasThreadAccess"); | ||
|
||
/// <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="dispatcher">A <see cref="DispatcherQueue"/> whose foreground thread to switch execution to.</param> | ||
/// <param name="priority">Specifies the priority for event dispatch.</param> | ||
/// <returns>An object that you can <see langword="await"/>.</returns> | ||
public static DispatcherQueueThreadSwitcher ResumeForegroundAsync(this DispatcherQueue dispatcher, DispatcherQueuePriority priority = DispatcherQueuePriority.Normal) => new DispatcherQueueThreadSwitcher(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="dispatcher">A <see cref="CoreDispatcher"/> whose foreground thread to switch execution to.</param> | ||
/// <param name="priority">Specifies the priority for event dispatch.</param> | ||
/// <returns>An object that you can <see langword="await"/>.</returns> | ||
public static CoreDispatcherThreadSwitcher ResumeForegroundAsync(this CoreDispatcher dispatcher, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal) => new CoreDispatcherThreadSwitcher(dispatcher, priority); | ||
|
||
/// <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> | ||
/// <param name="priority">Specifies the priority for event dispatch.</param> | ||
/// <returns>An object that you can <see langword="await"/>.</returns> | ||
public static ThreadPoolThreadSwitcher ResumeBackgroundAsync(WorkItemPriority priority = WorkItemPriority.Normal) => new ThreadPoolThreadSwitcher(priority); | ||
} | ||
} |
Oops, something went wrong.