初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器 HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块 Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚 AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PCL.Core.UI.Animation.UIAccessProvider;
|
||||
|
||||
/// <summary>
|
||||
/// 跨框架的 UI 线程访问接口。
|
||||
/// </summary>
|
||||
public interface IUIAccessProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否在 UI 线程。
|
||||
/// </summary>
|
||||
bool CheckAccess();
|
||||
|
||||
/// <summary>
|
||||
/// 在 UI 线程同步执行。
|
||||
/// 如果当前就在 UI 线程,则直接执行。
|
||||
/// </summary>
|
||||
void Invoke(Action action);
|
||||
|
||||
/// <summary>
|
||||
/// 在 UI 线程异步执行。
|
||||
/// 如果当前就在 UI 线程,则直接执行。
|
||||
/// </summary>
|
||||
Task InvokeAsync(Action action);
|
||||
|
||||
/// <summary>
|
||||
/// 在 UI 线程异步执行,并返回结果。
|
||||
/// </summary>
|
||||
Task<T> InvokeAsync<T>(Func<T> func);
|
||||
|
||||
/// <summary>
|
||||
/// 在 UI 线程异步执行 Task。
|
||||
/// </summary>
|
||||
Task InvokeAsync(Func<Task> func);
|
||||
|
||||
/// <summary>
|
||||
/// 在 UI 线程异步执行 Task,并返回结果。
|
||||
/// </summary>
|
||||
Task<T> InvokeAsync<T>(Func<Task<T>> func);
|
||||
|
||||
/// <summary>
|
||||
/// UI 渲染时执行的事件。
|
||||
/// </summary>
|
||||
event EventHandler FrameTick;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace PCL.Core.UI.Animation.UIAccessProvider;
|
||||
|
||||
public sealed class WpfUIAccessProvider(Dispatcher dispatcher) : IUIAccessProvider
|
||||
{
|
||||
private readonly Dispatcher _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
|
||||
|
||||
public bool CheckAccess() => _dispatcher.CheckAccess();
|
||||
|
||||
public void Invoke(Action action)
|
||||
{
|
||||
if (_dispatcher.CheckAccess())
|
||||
action();
|
||||
else
|
||||
_dispatcher.Invoke(action, DispatcherPriority.Send);
|
||||
}
|
||||
|
||||
public Task InvokeAsync(Action action)
|
||||
{
|
||||
if (!_dispatcher.CheckAccess()) return _dispatcher.InvokeAsync(action, DispatcherPriority.Send).Task;
|
||||
action();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<T> InvokeAsync<T>(Func<T> func)
|
||||
{
|
||||
return _dispatcher.CheckAccess() ? Task.FromResult(func()) : _dispatcher.InvokeAsync(func, DispatcherPriority.Send).Task;
|
||||
}
|
||||
|
||||
public Task InvokeAsync(Func<Task> func)
|
||||
{
|
||||
return _dispatcher.CheckAccess() ? func() : _dispatcher.InvokeAsync(func, DispatcherPriority.Send).Task.Unwrap();
|
||||
}
|
||||
|
||||
public Task<T> InvokeAsync<T>(Func<Task<T>> func)
|
||||
{
|
||||
return _dispatcher.CheckAccess() ? func() : _dispatcher.InvokeAsync(func, DispatcherPriority.Send).Task.Unwrap();
|
||||
}
|
||||
|
||||
public event EventHandler FrameTick
|
||||
{
|
||||
add => Invoke(() => CompositionTarget.Rendering += value);
|
||||
remove => Invoke(() => CompositionTarget.Rendering -= value);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user