初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器 HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块 Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚 AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using PCL.Core.Logging;
|
||||
|
||||
namespace PCL.Core.App.Tasks;
|
||||
|
||||
/// <summary>
|
||||
/// 任务中心,用于管理任务
|
||||
/// </summary>
|
||||
public static class TaskCenter
|
||||
{
|
||||
/// <summary>
|
||||
/// 可观察的任务模型集合
|
||||
/// </summary>
|
||||
public static ObservableCollection<TaskModel> Tasks { get; } = [];
|
||||
|
||||
private static readonly ConditionalWeakTable<ITask, TaskModel> _ModelMap = [];
|
||||
|
||||
private static TaskModel _InitModel(ITask instance)
|
||||
{
|
||||
// ReSharper disable SuspiciousTypeConversion.Global
|
||||
var cancelable = instance as ITaskCancelable;
|
||||
var pausable = instance as ITaskPausable;
|
||||
var progressive = instance as ITaskProgressive;
|
||||
// ReSharper restore SuspiciousTypeConversion.Global
|
||||
|
||||
var model = new TaskModel
|
||||
{
|
||||
Title = instance.Title,
|
||||
SupportProgress = progressive is not null,
|
||||
OnCancel = cancelable is null ? null : (() => cancelable.Cancel()),
|
||||
OnPause = pausable is null ? null : (() => pausable.Pause()),
|
||||
};
|
||||
|
||||
// state event
|
||||
instance.StateChanged += (state, message) =>
|
||||
{
|
||||
LogWrapper.Trace("TaskCenter", $"{instance.Title}: state changed ({state}): {message}");
|
||||
model.State = state;
|
||||
model.StateMessage = message;
|
||||
};
|
||||
|
||||
// progress event
|
||||
if (progressive is not null)
|
||||
{
|
||||
progressive.ProgressChanged += progress =>
|
||||
{
|
||||
model.Progress = Math.Clamp(progress, 0.0, 1.0);
|
||||
};
|
||||
}
|
||||
|
||||
// group events
|
||||
if (instance is ITaskGroup group)
|
||||
{
|
||||
group.AddTask += task =>
|
||||
{
|
||||
var taskModel = _InitModel(task);
|
||||
_ModelMap.Add(task, taskModel);
|
||||
model.Children.Add(taskModel);
|
||||
};
|
||||
group.RemoveTask += task =>
|
||||
{
|
||||
if (_ModelMap.TryGetValue(task, out var taskModel)) model.Children.Remove(taskModel);
|
||||
};
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册响应式任务实例
|
||||
/// </summary>
|
||||
/// <param name="instance">任务实例</param>
|
||||
/// <param name="start">是否立即启动该实例</param>
|
||||
public static void Register(ITask instance, bool start = true)
|
||||
{
|
||||
var model = _InitModel(instance);
|
||||
Tasks.Add(model);
|
||||
|
||||
if (start)
|
||||
{
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
try { await instance.ExecuteAsync(); }
|
||||
catch (OperationCanceledException) { /* ignoring */ }
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogWrapper.Warn(ex, "TaskCenter", $"{instance.Title}: exception thrown");
|
||||
model.State = TaskState.Failed;
|
||||
model.StateMessage = ex.Message;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除所有已结束的任务
|
||||
/// </summary>
|
||||
public static void RemoveFinished()
|
||||
{
|
||||
foreach (var model in Tasks.Where(x => x.State > TaskState.Running).ToList())
|
||||
Tasks.Remove(model);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user