我正在嘗試在 C# 中創建一個任務跟蹤器。每個任務都有一個唯一的 id/name 和一個運行“每個 id 一個實體可以同時運行”的任務。
我創建了以下類來跟蹤任務
public partial class ProgressTracker : IProgressTracker
{
private ConcurrentDictionary<string, TrackedProgress> _tracker;
public ProgressTracker()
{
_tracker = new ConcurrentDictionary<string, TrackedProgress>();
}
public bool TryStart(string name, Task task)
{
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentNullException(nameof(name));
}
return _tracker.TryAdd(name, new TrackedProgress(task));
}
public bool TryFinish(string name, out int? duration)
{
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentNullException(nameof(name));
}
duration = null;
if (_tracker.TryRemove(name, out TrackedProgress progress))
{
duration = (int)DateTime.Now.Subtract(progress.StartedAt).TotalSeconds;
return true;
}
return false;
}
public bool IsRunning(string name, out int? duration)
{
duration = null;
if (_tracker.TryGetValue(name, out TrackedProgress progress))
{
duration = (int)DateTime.Now.Subtract(progress.StartedAt).TotalSeconds;
return true;
}
return false;
}
public bool TryAbort(string name, out int? duration)
{
duration = null;
if (_tracker.TryGetValue(name, out TrackedProgress progress))
{
if(!progress.Job.IsCanceled && !progress.Job.IsCompleted)
{
// How can I abort progress.Job task
}
duration = (int)DateTime.Now.Subtract(progress.StartedAt).TotalSeconds;
return true;
}
return false;
}
}
這是包含有關跟蹤任務的資料的類。
public sealed class TrackedProgress
{
internal DateTime StartedAt { get; set; }
public Task Job { get; set; }
public int? Duration { get; set; }
public TrackedProgress(Task job)
{
StartedAt = DateTime.Now;
Job = job;
}
public TrackedProgress(DateTime startedAt, Task job)
{
StartedAt = startedAt;
Job = job;
}
}
由于我正在跟蹤 a Task,我如何根據要求中止它?
uj5u.com熱心網友回復:
您可以將 cts 添加到 TrackedProgress 類:
public sealed class TrackedProgress
{
internal DateTime StartedAt { get; set; }
public Task Job { get; set; }
public CancellationTokenSource Cts { get; }
public int? Duration { get; set; }
public TrackedProgress(Task job, CancellationTokenSource cts)
{
StartedAt = DateTime.Now;
Job = job;
Cts = cts;
}
public TrackedProgress(DateTime startedAt, Task job, CancellationTokenSource cts)
{
StartedAt = startedAt;
Job = job;
Cts = cts;
}
}
ProgressTracker 中的一些變化:
public partial class ProgressTracker
{
private ConcurrentDictionary<string, TrackedProgress> _tracker;
public ProgressTracker()
{
_tracker = new ConcurrentDictionary<string, TrackedProgress>();
}
//Here - add the cts
public bool TryStart(string name, Task task, CancellationTokenSource cts)
{
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentNullException(nameof(name));
}
return _tracker.TryAdd(name, new TrackedProgress(task, cts));
}
public bool TryFinish(string name, out int? duration)
{
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentNullException(nameof(name));
}
duration = null;
if (_tracker.TryRemove(name, out TrackedProgress progress))
{
duration = (int)DateTime.Now.Subtract(progress.StartedAt).TotalSeconds;
return true;
}
return false;
}
public bool IsRunning(string name, out int? duration)
{
duration = null;
if (_tracker.TryGetValue(name, out TrackedProgress progress))
{
duration = (int)DateTime.Now.Subtract(progress.StartedAt).TotalSeconds;
return true;
}
return false;
}
public bool TryAbort(string name, out int? duration)
{
duration = null;
if (_tracker.TryGetValue(name, out TrackedProgress progress))
{
if(!progress.Job.IsCanceled && !progress.Job.IsCompleted)
{
// Cancelling the task
progress.Cts.Cancel();
}
duration = (int)DateTime.Now.Subtract(progress.StartedAt).TotalSeconds;
return true;
}
return false;
}
}
當然,您還需要確保在任務主體內處理取消!
uj5u.com熱心網友回復:
閱讀評論后,我調整了我的消費者類,這些類匯入可能需要時間的資料。這個類將接受一個任務和一個取消令牌。取消令牌與任務一起被跟蹤
跟蹤器類現在看起來像這樣
internal sealed class TrackedProgress
{
public DateTime StartedAt { get; private set; }
public Task Job { get; private set; }
public CancellationTokenSource CancellationToken { get; private set; }
public int? Duration { get; private set; }
public TrackedProgress(Task job, CancellationToken cancellationToken)
: this(DateTime.Now, job, cancellationToken)
{
}
public TrackedProgress(DateTime startedAt, Task job, CancellationToken cancellationToken)
{
StartedAt = startedAt;
Job = job;
CancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
}
public void Abort()
{
CancellationToken?.Cancel();
}
public bool IsRunning()
{
if (Job == null)
{
return false;
}
return !Job.IsCompleted && !Job.IsCanceled;
}
}
tracker類修改為這個
public partial class ProgressTracker : IProgressTracker
{
private ConcurrentDictionary<string, TrackedProgress> _tracker;
public ProgressTracker()
{
_tracker = new ConcurrentDictionary<string, TrackedProgress>();
}
public bool TryStart(string name, Task task, CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentNullException(nameof(name));
}
return _tracker.TryAdd(name, new TrackedProgress(task, cancellationToken));
}
public bool TryFinish(string name, out int? duration)
{
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentNullException(nameof(name));
}
duration = null;
if (_tracker.TryRemove(name, out TrackedProgress progress))
{
if(progress.IsRunning())
{
return false;
}
duration = (int)DateTime.Now.Subtract(progress.StartedAt).TotalSeconds;
return true;
}
return false;
}
public bool IsTracked(string name, out int? duration)
{
duration = null;
if (_tracker.TryGetValue(name, out TrackedProgress progress))
{
duration = (int)DateTime.Now.Subtract(progress.StartedAt).TotalSeconds;
return true;
}
return false;
}
public bool TryAbort(string name, out int? duration)
{
duration = null;
if (_tracker.TryGetValue(name, out TrackedProgress progress))
{
if(progress.IsRunning())
{
progress.Abort();
}
duration = (int)DateTime.Now.Subtract(progress.StartedAt).TotalSeconds;
return true;
}
return false;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/321429.html
