Procházet zdrojové kódy

RedoableWorker 的一些扩展

龙腾猫跃 před 4 měsíci
rodič
revize
8b26dccd22

+ 12 - 0
Shared/General/Progress.cs

@@ -62,6 +62,18 @@ public class ProgressProvider {
     public void Finish(ChildrenAction action = ChildrenAction.Finished) => Set(1, skiped: false, action: action);
     public void Finish(ChildrenAction action = ChildrenAction.Finished) => Set(1, skiped: false, action: action);
     /// <summary>跳过当前项的剩余进度。</summary>
     /// <summary>跳过当前项的剩余进度。</summary>
     public void Skip(ChildrenAction action = ChildrenAction.Skiped) => Set(1, skiped: true, action: action);
     public void Skip(ChildrenAction action = ChildrenAction.Skiped) => Set(1, skiped: true, action: action);
+    /// <summary>
+    /// 重置当前进度,并清除所有子项。
+    /// </summary>
+    public void Reset() {
+        bool changed;
+        lock (this) {
+            changed = progressSum > 0;
+            progressParts = (0, 0, 0);
+            childrens.Clear();
+        }
+        if (changed) InvokeProgressChanged();
+    }
 
 
     // ===================================== 子项进度 =====================================
     // ===================================== 子项进度 =====================================
 
 

+ 29 - 9
Shared/General/Workers/RedoableWorker.cs

@@ -21,17 +21,27 @@ public interface IRedoableWorker {
 }
 }
 
 
 /// <inheritdoc cref="IRedoableWorker"/>
 /// <inheritdoc cref="IRedoableWorker"/>
-public abstract class RedoableWorkerBase<TOut>(Func<CancellationToken, TOut> workload) : IRedoableWorker {
+public abstract class RedoableWorkerBase<TOut>(Func<CancellationToken?, ProgressProvider?, TOut> workload, ProgressProvider? p = null) : IRedoableWorker {
 
 
-    // ============================================ 状态 ============================================
+    // ============================================ 状态与事件 ============================================
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
     public bool Running { get { lock (this) return running; } }
     public bool Running { get { lock (this) return running; } }
     private bool running;
     private bool running;
+    /// <summary>从空闲状态进入运行状态时触发。</summary>
+    public event Action? Started;
+    /// <summary>运行结束并进入空闲状态时触发。</summary>
+    public event Action? Stopped;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
     public bool HasSucceeded { get { lock (this) return hasSucceeded; } }
     public bool HasSucceeded { get { lock (this) return hasSucceeded; } }
     private bool hasSucceeded;
     private bool hasSucceeded;
+    /// <summary>工作负载成功完成时触发,参数为返回值。这可能会在重启前触发。</summary>
+    public event Action<TOut>? Succeeded;
+    /// <summary>工作负载执行失败时触发,参数为发生的异常。这可能会在重启前触发。</summary>
+    public event Action<Exception>? Failed;
+    /// <summary>运行被取消时触发。这可能会在重启前触发。</summary>
+    public event Action? Canceled;
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
     public bool LastSucceeded { get { lock (this) return lastSucceeded; } }
     public bool LastSucceeded { get { lock (this) return lastSucceeded; } }
@@ -73,10 +83,12 @@ public abstract class RedoableWorkerBase<TOut>(Func<CancellationToken, TOut> wor
         th.Start();
         th.Start();
     }
     }
     private void _Invoke() {
     private void _Invoke() {
+        Started?.Invoke();
         while (true) {
         while (true) {
             try {
             try {
                 realCts!.Token.ThrowIfCancellationRequested();
                 realCts!.Token.ThrowIfCancellationRequested();
-                TOut result = workload(realCts.Token); // 实际的执行
+                p?.Reset();
+                TOut result = workload(realCts.Token, p); // 实际的执行
                 realCts.Token.ThrowIfCancellationRequested();
                 realCts.Token.ThrowIfCancellationRequested();
                 lock (this) {
                 lock (this) {
                     realCts?.Dispose();
                     realCts?.Dispose();
@@ -91,9 +103,14 @@ public abstract class RedoableWorkerBase<TOut>(Func<CancellationToken, TOut> wor
                     hasSucceeded = true;
                     hasSucceeded = true;
                     running = false; idleEvent.Set();
                     running = false; idleEvent.Set();
                 }
                 }
+                Succeeded?.Invoke(result);
             } catch (Exception ex) {
             } catch (Exception ex) {
-                if (!ex.IsCanceled()) 
+                if (ex.IsCanceled()) {
+                    Canceled?.Invoke();
+                } else {
+                    Failed?.Invoke(ex);
                     Logger.Log(ex, $"工作线程执行失败{(pendingRedo ? ",但即将重启,或可忽略" : "")}", pendingRedo ? LogLevel.Info : LogLevel.Warn);
                     Logger.Log(ex, $"工作线程执行失败{(pendingRedo ? ",但即将重启,或可忽略" : "")}", pendingRedo ? LogLevel.Info : LogLevel.Warn);
+                }
                 lock (this) {
                 lock (this) {
                     realCts?.Dispose();
                     realCts?.Dispose();
                     if (pendingRedo) { // 接取重启请求
                     if (pendingRedo) { // 接取重启请求
@@ -106,8 +123,9 @@ public abstract class RedoableWorkerBase<TOut>(Func<CancellationToken, TOut> wor
                     running = false; idleEvent.Set();
                     running = false; idleEvent.Set();
                 }
                 }
             }
             }
-            return;
+            break;
         }
         }
+        Stopped?.Invoke();
     }
     }
 
 
     /// <inheritdoc/>
     /// <inheritdoc/>
@@ -126,12 +144,14 @@ public abstract class RedoableWorkerBase<TOut>(Func<CancellationToken, TOut> wor
 
 
 /// <inheritdoc />
 /// <inheritdoc />
 public class RedoableWorker<TOut> : RedoableWorkerBase<TOut> {
 public class RedoableWorker<TOut> : RedoableWorkerBase<TOut> {
-    public RedoableWorker(Func<CancellationToken, TOut> workload) : base(workload) { }
-    public RedoableWorker(Func<TOut> workload) : base(_ => workload()) { }
+    public RedoableWorker(Func<CancellationToken?, ProgressProvider?, TOut> workload) : base(workload) { }
+    public RedoableWorker(Func<CancellationToken?, TOut> workload) : base((c, _) => workload(c)) { }
+    public RedoableWorker(Func<TOut> workload) : base((_, _) => workload()) { }
 }
 }
 
 
 /// <inheritdoc />
 /// <inheritdoc />
 public class RedoableWorker : RedoableWorkerBase<object?> {
 public class RedoableWorker : RedoableWorkerBase<object?> {
-    public RedoableWorker(Action<CancellationToken> workload) : base(ct => { workload(ct); return null; }) { }
-    public RedoableWorker(Action workload) : base(_ => { workload(); return null; }) { }
+    public RedoableWorker(Func<CancellationToken?, ProgressProvider?, object?> workload) : base(workload) { }
+    public RedoableWorker(Action<CancellationToken?> workload) : base((c, _) => { workload(c); return null; }) { }
+    public RedoableWorker(Action workload) : base((_, _) => { workload(); return null; }) { }
 }
 }