mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
refactor
This commit is contained in:
@@ -18,7 +18,6 @@ using Snap.Hutao.Service.Metadata;
|
||||
using Snap.Hutao.Service.Navigation;
|
||||
using Snap.Hutao.ViewModel.Guide;
|
||||
using System.Diagnostics;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Snap.Hutao.Core.LifeCycle;
|
||||
|
||||
|
||||
@@ -21,11 +21,6 @@ internal static class AppInstanceExtension
|
||||
// Hold the reference here to prevent memory corruption.
|
||||
private static HANDLE redirectEventHandle;
|
||||
|
||||
/// <summary>
|
||||
/// 同步非阻塞重定向
|
||||
/// </summary>
|
||||
/// <param name="appInstance">app实例</param>
|
||||
/// <param name="args">参数</param>
|
||||
public static unsafe void RedirectActivationTo(this AppInstance appInstance, AppActivationArguments args)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -5,117 +5,96 @@ using Windows.Storage;
|
||||
|
||||
namespace Snap.Hutao.Core.Setting;
|
||||
|
||||
/// <summary>
|
||||
/// 本地设置
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal static class LocalSetting
|
||||
{
|
||||
private static readonly ApplicationDataContainer Container = ApplicationData.Current.LocalSettings;
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static byte Get(string key, byte defaultValue)
|
||||
{
|
||||
return Get<byte>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static short Get(string key, short defaultValue)
|
||||
{
|
||||
return Get<short>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static ushort Get(string key, ushort defaultValue)
|
||||
{
|
||||
return Get<ushort>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static int Get(string key, int defaultValue)
|
||||
{
|
||||
return Get<int>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static uint Get(string key, uint defaultValue)
|
||||
{
|
||||
return Get<uint>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static long Get(string key, long defaultValue)
|
||||
{
|
||||
return Get<long>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static ulong Get(string key, ulong defaultValue)
|
||||
{
|
||||
return Get<ulong>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static float Get(string key, float defaultValue)
|
||||
{
|
||||
return Get<float>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static double Get(string key, double defaultValue)
|
||||
{
|
||||
return Get<double>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static bool Get(string key, bool defaultValue)
|
||||
{
|
||||
return Get<bool>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static char Get(string key, char defaultValue)
|
||||
{
|
||||
return Get<char>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static string Get(string key, string defaultValue)
|
||||
{
|
||||
return Get<string>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static DateTimeOffset Get(string key, in DateTimeOffset defaultValue)
|
||||
{
|
||||
return Get<DateTimeOffset>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static TimeSpan Get(string key, in TimeSpan defaultValue)
|
||||
{
|
||||
return Get<TimeSpan>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static Guid Get(string key, in Guid defaultValue)
|
||||
{
|
||||
return Get<Guid>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static Windows.Foundation.Point Get(string key, Windows.Foundation.Point defaultValue)
|
||||
{
|
||||
return Get<Windows.Foundation.Point>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static Windows.Foundation.Size Get(string key, Windows.Foundation.Size defaultValue)
|
||||
{
|
||||
return Get<Windows.Foundation.Size>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static Windows.Foundation.Rect Get(string key, Windows.Foundation.Rect defaultValue)
|
||||
{
|
||||
return Get<Windows.Foundation.Rect>(key, defaultValue);
|
||||
@@ -126,109 +105,91 @@ internal static class LocalSetting
|
||||
return Get<ApplicationDataCompositeValue>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Set{T}(string, T)"/>
|
||||
public static void Set(string key, byte value)
|
||||
{
|
||||
Set<byte>(key, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Set{T}(string, T)"/>
|
||||
public static void Set(string key, short value)
|
||||
{
|
||||
Set<short>(key, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Set{T}(string, T)"/>
|
||||
public static void Set(string key, ushort value)
|
||||
{
|
||||
Set<ushort>(key, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Set{T}(string, T)"/>
|
||||
public static void Set(string key, int value)
|
||||
{
|
||||
Set<int>(key, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Set{T}(string, T)"/>
|
||||
public static void Set(string key, uint value)
|
||||
{
|
||||
Set<uint>(key, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Set{T}(string, T)"/>
|
||||
public static void Set(string key, long value)
|
||||
{
|
||||
Set<long>(key, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Set{T}(string, T)"/>
|
||||
public static void Set(string key, ulong value)
|
||||
{
|
||||
Set<ulong>(key, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Set{T}(string, T)"/>
|
||||
public static void Set(string key, float value)
|
||||
{
|
||||
Set<float>(key, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Set{T}(string, T)"/>
|
||||
public static void Set(string key, double value)
|
||||
{
|
||||
Set<double>(key, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Set{T}(string, T)"/>
|
||||
public static void Set(string key, bool value)
|
||||
{
|
||||
Set<bool>(key, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Set{T}(string, T)"/>
|
||||
public static void Set(string key, char value)
|
||||
{
|
||||
Set<char>(key, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Set{T}(string, T)"/>
|
||||
public static void Set(string key, string value)
|
||||
{
|
||||
Set<string>(key, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Set{T}(string, T)"/>
|
||||
public static void Set(string key, in DateTimeOffset value)
|
||||
{
|
||||
Set<DateTimeOffset>(key, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Set{T}(string, T)"/>
|
||||
public static void Set(string key, in TimeSpan value)
|
||||
{
|
||||
Set<TimeSpan>(key, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Set{T}(string, T)"/>
|
||||
public static void Set(string key, in Guid value)
|
||||
{
|
||||
Set<Guid>(key, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Set{T}(string, T)"/>
|
||||
public static void Set(string key, Windows.Foundation.Point value)
|
||||
{
|
||||
Set<Windows.Foundation.Point>(key, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Set{T}(string, T)"/>
|
||||
public static void Set(string key, Windows.Foundation.Size value)
|
||||
{
|
||||
Set<Windows.Foundation.Size>(key, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Set{T}(string, T)"/>
|
||||
public static void Set(string key, Windows.Foundation.Rect value)
|
||||
{
|
||||
Set<Windows.Foundation.Rect>(key, value);
|
||||
|
||||
@@ -3,26 +3,11 @@
|
||||
|
||||
namespace Snap.Hutao.Core.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// An asynchronous barrier that blocks the signaler until all other participants have signaled.
|
||||
/// FIFO
|
||||
/// </summary>
|
||||
internal class AsyncBarrier
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of participants being synchronized.
|
||||
/// </summary>
|
||||
private readonly int participantCount;
|
||||
|
||||
/// <summary>
|
||||
/// The set of participants who have reached the barrier, with their awaiters that can resume those participants.
|
||||
/// </summary>
|
||||
private readonly Queue<TaskCompletionSource> waiters;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AsyncBarrier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="participants">The number of participants.</param>
|
||||
public AsyncBarrier(int participants)
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(participants, "Participants of AsyncBarrier must be greater than 0");
|
||||
@@ -33,11 +18,6 @@ internal class AsyncBarrier
|
||||
waiters = new Queue<TaskCompletionSource>(participants - 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Signals that a participant is ready, and returns a Task
|
||||
/// that completes when all other participants have also signaled ready.
|
||||
/// </summary>
|
||||
/// <returns>A Task, which will complete (or may already be completed) when the last participant calls this method.</returns>
|
||||
[SuppressMessage("", "SH007")]
|
||||
public ValueTask SignalAndWaitAsync()
|
||||
{
|
||||
|
||||
@@ -3,22 +3,17 @@
|
||||
|
||||
namespace Snap.Hutao.Core.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// 无区分项的并发<see cref="CancellationTokenSource"/>
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[SuppressMessage("", "CA1001")]
|
||||
internal class ConcurrentCancellationTokenSource
|
||||
{
|
||||
private CancellationTokenSource source = new();
|
||||
|
||||
/// <summary>
|
||||
/// 注册取消令牌
|
||||
/// </summary>
|
||||
/// <returns>取消令牌</returns>
|
||||
public CancellationToken Register()
|
||||
{
|
||||
source.Cancel();
|
||||
source.Dispose();
|
||||
|
||||
source = new();
|
||||
return source.Token;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
|
||||
namespace Snap.Hutao.Core.Threading;
|
||||
|
||||
#if NET9_0_OR_GREATER
|
||||
[Obsolete]
|
||||
#endif
|
||||
internal readonly struct Delay
|
||||
{
|
||||
/// <summary>
|
||||
@@ -16,14 +18,4 @@ internal readonly struct Delay
|
||||
{
|
||||
return Task.Delay((int)(System.Random.Shared.NextDouble() * (max - min)) + min).AsValueTask();
|
||||
}
|
||||
|
||||
public static ValueTask FromSeconds(int seconds)
|
||||
{
|
||||
return Task.Delay(TimeSpan.FromSeconds(seconds)).AsValueTask();
|
||||
}
|
||||
|
||||
public static ValueTask FromMilliSeconds(int seconds)
|
||||
{
|
||||
return Task.Delay(TimeSpan.FromMilliseconds(seconds)).AsValueTask();
|
||||
}
|
||||
}
|
||||
@@ -6,17 +6,9 @@ using System.Runtime.ExceptionServices;
|
||||
|
||||
namespace Snap.Hutao.Core.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// 调度器队列拓展
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal static class DispatcherQueueExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 在调度器队列同步调用,直到执行结束,会持续阻塞当前线程
|
||||
/// </summary>
|
||||
/// <param name="dispatcherQueue">调度器队列</param>
|
||||
/// <param name="action">执行的回调</param>
|
||||
public static void Invoke(this DispatcherQueue dispatcherQueue, Action action)
|
||||
{
|
||||
if (dispatcherQueue.HasThreadAccess)
|
||||
@@ -49,13 +41,6 @@ internal static class DispatcherQueueExtension
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在调度器队列同步调用,直到执行结束,会持续阻塞当前线程
|
||||
/// </summary>
|
||||
/// <param name="dispatcherQueue">调度器队列</param>
|
||||
/// <param name="action">执行的回调</param>
|
||||
/// <typeparam name="T">返回类型</typeparam>
|
||||
/// <returns>回调返回值</returns>
|
||||
public static T Invoke<T>(this DispatcherQueue dispatcherQueue, Func<T> action)
|
||||
{
|
||||
T result = default!;
|
||||
|
||||
@@ -6,48 +6,35 @@ using Snap.Hutao.Core.Threading.Abstraction;
|
||||
|
||||
namespace Snap.Hutao.Core.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// 调度器队列切换操作
|
||||
/// 等待此类型对象后上下文会被切换至主线程
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal readonly struct DispatcherQueueSwitchOperation : IAwaitable<DispatcherQueueSwitchOperation>, ICriticalAwaiter
|
||||
{
|
||||
private readonly DispatcherQueue dispatherQueue;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的调度器队列等待器
|
||||
/// </summary>
|
||||
/// <param name="dispatherQueue">调度器队列</param>
|
||||
public DispatcherQueueSwitchOperation(DispatcherQueue dispatherQueue)
|
||||
{
|
||||
this.dispatherQueue = dispatherQueue;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool IsCompleted
|
||||
{
|
||||
get => dispatherQueue.HasThreadAccess;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public DispatcherQueueSwitchOperation GetAwaiter()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void GetResult()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnCompleted(Action continuation)
|
||||
{
|
||||
dispatherQueue.TryEnqueue(new DispatcherQueueHandler(continuation));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void UnsafeOnCompleted(Action continuation)
|
||||
{
|
||||
using (ExecutionContext.SuppressFlow())
|
||||
|
||||
@@ -5,18 +5,12 @@ using Microsoft.UI.Dispatching;
|
||||
|
||||
namespace Snap.Hutao.Core.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// 任务上下文
|
||||
/// </summary>
|
||||
[Injection(InjectAs.Singleton, typeof(ITaskContext))]
|
||||
internal sealed class TaskContext : ITaskContext, ITaskContextUnsafe
|
||||
{
|
||||
private readonly DispatcherQueueSynchronizationContext synchronizationContext;
|
||||
private readonly DispatcherQueue dispatcherQueue;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的任务上下文
|
||||
/// </summary>
|
||||
public TaskContext()
|
||||
{
|
||||
dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||
@@ -26,25 +20,21 @@ internal sealed class TaskContext : ITaskContext, ITaskContextUnsafe
|
||||
|
||||
public DispatcherQueue DispatcherQueue { get => dispatcherQueue; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ThreadPoolSwitchOperation SwitchToBackgroundAsync()
|
||||
{
|
||||
return new(dispatcherQueue);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public DispatcherQueueSwitchOperation SwitchToMainThreadAsync()
|
||||
{
|
||||
return new(dispatcherQueue);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void InvokeOnMainThread(Action action)
|
||||
{
|
||||
dispatcherQueue.Invoke(action);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public T InvokeOnMainThread<T>(Func<T> action)
|
||||
{
|
||||
return dispatcherQueue.Invoke(action);
|
||||
|
||||
@@ -24,10 +24,6 @@ internal static class TaskExtension
|
||||
return new(task);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全的触发任务
|
||||
/// </summary>
|
||||
/// <param name="task">任务</param>
|
||||
public static async void SafeForget(this Task task)
|
||||
{
|
||||
try
|
||||
@@ -54,11 +50,6 @@ internal static class TaskExtension
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全的触发任务
|
||||
/// </summary>
|
||||
/// <param name="task">任务</param>
|
||||
/// <param name="logger">日志器</param>
|
||||
public static async void SafeForget(this Task task, ILogger logger)
|
||||
{
|
||||
try
|
||||
@@ -71,16 +62,10 @@ internal static class TaskExtension
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger?.LogError(e, "{Caller}:\r\n{Exception}", nameof(SafeForget), ExceptionFormat.Format(e.GetBaseException()));
|
||||
logger?.LogError(e, "SafeForget:\r\n{Exception}", ExceptionFormat.Format(e.GetBaseException()));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全的触发任务
|
||||
/// </summary>
|
||||
/// <param name="task">任务</param>
|
||||
/// <param name="logger">日志器</param>
|
||||
/// <param name="onException">发生异常时调用</param>
|
||||
public static async void SafeForget(this Task task, ILogger logger, Action<Exception> onException)
|
||||
{
|
||||
try
|
||||
@@ -93,18 +78,11 @@ internal static class TaskExtension
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger?.LogError(e, "{Caller}:\r\n{Exception}", nameof(SafeForget), ExceptionFormat.Format(e.GetBaseException()));
|
||||
logger?.LogError(e, "SafeForget:\r\n{Exception}", ExceptionFormat.Format(e.GetBaseException()));
|
||||
onException?.Invoke(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全的触发任务
|
||||
/// </summary>
|
||||
/// <param name="task">任务</param>
|
||||
/// <param name="logger">日志器</param>
|
||||
/// <param name="onCanceled">任务取消时调用</param>
|
||||
/// <param name="onException">发生异常时调用</param>
|
||||
public static async void SafeForget(this Task task, ILogger logger, Action onCanceled, Action<Exception>? onException = null)
|
||||
{
|
||||
try
|
||||
@@ -117,15 +95,11 @@ internal static class TaskExtension
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger?.LogError(e, "{Caller}:\r\n{Exception}", nameof(SafeForget), ExceptionFormat.Format(e.GetBaseException()));
|
||||
logger?.LogError(e, "SafeForget:\r\n{Exception}", ExceptionFormat.Format(e.GetBaseException()));
|
||||
onException?.Invoke(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全的触发任务
|
||||
/// </summary>
|
||||
/// <param name="task">任务</param>
|
||||
public static async void SafeForget(this ValueTask task)
|
||||
{
|
||||
try
|
||||
@@ -152,11 +126,6 @@ internal static class TaskExtension
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全的触发任务
|
||||
/// </summary>
|
||||
/// <param name="task">任务</param>
|
||||
/// <param name="logger">日志器</param>
|
||||
public static async void SafeForget(this ValueTask task, ILogger logger)
|
||||
{
|
||||
try
|
||||
@@ -169,16 +138,10 @@ internal static class TaskExtension
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger?.LogError(e, "{Caller}:\r\n{Exception}", nameof(SafeForget), ExceptionFormat.Format(e.GetBaseException()));
|
||||
logger?.LogError(e, "SafeForget:\r\n{Exception}", ExceptionFormat.Format(e.GetBaseException()));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全的触发任务
|
||||
/// </summary>
|
||||
/// <param name="task">任务</param>
|
||||
/// <param name="logger">日志器</param>
|
||||
/// <param name="onException">发生异常时调用</param>
|
||||
public static async void SafeForget(this ValueTask task, ILogger logger, Action<Exception> onException)
|
||||
{
|
||||
try
|
||||
@@ -191,18 +154,11 @@ internal static class TaskExtension
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger?.LogError(e, "{Caller}:\r\n{Exception}", nameof(SafeForget), ExceptionFormat.Format(e.GetBaseException()));
|
||||
logger?.LogError(e, "SafeForget:\r\n{Exception}", ExceptionFormat.Format(e.GetBaseException()));
|
||||
onException?.Invoke(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全的触发任务
|
||||
/// </summary>
|
||||
/// <param name="task">任务</param>
|
||||
/// <param name="logger">日志器</param>
|
||||
/// <param name="onCanceled">任务取消时调用</param>
|
||||
/// <param name="onException">发生异常时调用</param>
|
||||
public static async void SafeForget(this ValueTask task, ILogger logger, Action onCanceled, Action<Exception>? onException = null)
|
||||
{
|
||||
try
|
||||
@@ -215,7 +171,7 @@ internal static class TaskExtension
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger?.LogError(e, "{Caller}:\r\n{Exception}", nameof(SafeForget), ExceptionFormat.Format(e.GetBaseException()));
|
||||
logger?.LogError(e, "SafeForget:\r\n{Exception}", ExceptionFormat.Format(e.GetBaseException()));
|
||||
onException?.Invoke(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,49 +6,36 @@ using Snap.Hutao.Core.Threading.Abstraction;
|
||||
|
||||
namespace Snap.Hutao.Core.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// 线程池切换操作
|
||||
/// 等待此类型对象后上下文会被切换至线程池线程
|
||||
/// </summary>
|
||||
internal readonly struct ThreadPoolSwitchOperation : IAwaitable<ThreadPoolSwitchOperation>, ICriticalAwaiter
|
||||
{
|
||||
private static readonly WaitCallback WaitCallbackRunAction = RunAction;
|
||||
private readonly DispatcherQueue dispatherQueue;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的线程池切换操作
|
||||
/// </summary>
|
||||
/// <param name="dispatherQueue">主线程队列</param>
|
||||
public ThreadPoolSwitchOperation(DispatcherQueue dispatherQueue)
|
||||
{
|
||||
this.dispatherQueue = dispatherQueue;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool IsCompleted
|
||||
{
|
||||
// 如果已经处于后台就不再切换新的线程
|
||||
get => !dispatherQueue.HasThreadAccess;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ThreadPoolSwitchOperation GetAwaiter()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void GetResult()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void OnCompleted(Action continuation)
|
||||
{
|
||||
QueueContinuation(continuation, true);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void UnsafeOnCompleted(Action continuation)
|
||||
{
|
||||
QueueContinuation(continuation, false);
|
||||
|
||||
@@ -5,39 +5,17 @@ using Snap.Hutao.Core.Abstraction;
|
||||
|
||||
namespace Snap.Hutao.Core.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// 用于包装异步操作的结果
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">结果类型</typeparam>
|
||||
/// <typeparam name="TValue">值类型</typeparam>
|
||||
internal readonly struct ValueResult<TResult, TValue> : IDeconstruct<TResult, TValue>
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否成功
|
||||
/// </summary>
|
||||
public readonly TResult IsOk;
|
||||
|
||||
/// <summary>
|
||||
/// 值
|
||||
/// </summary>
|
||||
public readonly TValue Value;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的结果
|
||||
/// </summary>
|
||||
/// <param name="isOk">是否成功</param>
|
||||
/// <param name="value">值</param>
|
||||
public ValueResult(TResult isOk, TValue value)
|
||||
{
|
||||
IsOk = isOk;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用于元组析构
|
||||
/// </summary>
|
||||
/// <param name="isOk">是否成功</param>
|
||||
/// <param name="value">值</param>
|
||||
public void Deconstruct(out TResult isOk, out TValue value)
|
||||
{
|
||||
isOk = IsOk;
|
||||
|
||||
@@ -3,18 +3,8 @@
|
||||
|
||||
namespace Snap.Hutao.Core.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// 结果扩展
|
||||
/// </summary>
|
||||
internal static class ValueResultExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 尝试获取结果的值
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">值的类型</typeparam>
|
||||
/// <param name="valueResult">结果</param>
|
||||
/// <param name="value">值</param>
|
||||
/// <returns>是否获取成功</returns>
|
||||
public static bool TryGetValue<TValue>(this in ValueResult<bool, TValue> valueResult, [NotNullWhen(true)] out TValue value)
|
||||
{
|
||||
value = valueResult.Value;
|
||||
|
||||
@@ -33,6 +33,7 @@ internal sealed class HotKeyCombination : ObservableObject
|
||||
private HOT_KEY_MODIFIERS modifiers;
|
||||
private VirtualKey key;
|
||||
private bool isEnabled;
|
||||
private bool isOn;
|
||||
|
||||
[SuppressMessage("", "SH002")]
|
||||
public HotKeyCombination(IServiceProvider serviceProvider, HWND hwnd, string settingKey, int hotKeyId, HOT_KEY_MODIFIERS defaultModifiers, VirtualKey defaultKey)
|
||||
@@ -162,6 +163,12 @@ internal sealed class HotKeyCombination : ObservableObject
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsOn
|
||||
{
|
||||
get => isOn;
|
||||
set => SetProperty(ref isOn, value);
|
||||
}
|
||||
|
||||
public string DisplayName { get => ToString(); }
|
||||
|
||||
public bool Register()
|
||||
|
||||
@@ -8,6 +8,8 @@ using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using static Snap.Hutao.Win32.ConstValues;
|
||||
using static Snap.Hutao.Win32.User32;
|
||||
using static Snap.Hutao.Win32.Kernel32;
|
||||
using static Snap.Hutao.Win32.Macros;
|
||||
|
||||
namespace Snap.Hutao.Core.Windowing.HotKey;
|
||||
|
||||
@@ -39,7 +41,7 @@ internal sealed class HotKeyMessageWindow : IDisposable
|
||||
|
||||
if (HWND == default)
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(Marshal.GetLastPInvokeError());
|
||||
Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(GetLastError()));
|
||||
}
|
||||
|
||||
WindowTable.TryAdd(HWND, this);
|
||||
|
||||
@@ -120,19 +120,19 @@ internal sealed partial class HotKeyOptions : ObservableObject, IDisposable
|
||||
{
|
||||
lock (syncRoot)
|
||||
{
|
||||
if (IsMouseClickRepeatForeverOn)
|
||||
if (MouseClickRepeatForeverKeyCombination.IsOn)
|
||||
{
|
||||
// Turn off
|
||||
cancellationTokenSource?.Cancel();
|
||||
cancellationTokenSource = default;
|
||||
IsMouseClickRepeatForeverOn = false;
|
||||
MouseClickRepeatForeverKeyCombination.IsOn = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Turn on
|
||||
cancellationTokenSource = new();
|
||||
ThreadPool.QueueUserWorkItem(RunMouseClickRepeatForever, cancellationTokenSource.Token);
|
||||
IsMouseClickRepeatForeverOn = true;
|
||||
MouseClickRepeatForeverKeyCombination.IsOn = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ internal sealed partial class IdentifyMonitorWindow : Window
|
||||
window.Activate();
|
||||
}
|
||||
|
||||
await Delay.FromSeconds(secondsDelay).ConfigureAwait(true);
|
||||
await Task.Delay(TimeSpan.FromSeconds(secondsDelay)).ConfigureAwait(true);
|
||||
|
||||
foreach (IdentifyMonitorWindow window in windows)
|
||||
{
|
||||
|
||||
@@ -9,10 +9,10 @@ namespace Snap.Hutao.Win32.UI.Input.KeyboardAndMouse;
|
||||
internal struct INPUT
|
||||
{
|
||||
public INPUT_TYPE type;
|
||||
public AnonymousUnion Anonymous;
|
||||
public Union Anonymous;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
internal struct AnonymousUnion
|
||||
internal struct Union
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public MOUSEINPUT mi;
|
||||
|
||||
Reference in New Issue
Block a user