108 lines
3.2 KiB
C#
108 lines
3.2 KiB
C#
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);
|
||
|
|
}
|
||
|
|
}
|