你提到的意思是跟蹤任務和擊球時獲得目標任務按鈕我的其他答案的評論之一鏈接,它看起來像鏈接描述如何使它可以取消。我已經適應我的例子來支持這一點:
private Dictionary<Guid, TaskTracker> _taskMap = new Dictionary<Guid, TaskTracker>();
private void OnButton1Click(object sender, EventArgs eventArgs)
{
TaskTracker taskTracker = new TaskTracker(Guid.NewGuid(), OnDoWork);
_taskMap.Add(taskTracker.Identity, taskTracker);
taskTracker.Start();
}
private void OnDoWork(CancellationToken token)
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(100); // Do some work, checking if cancel requested every once in a while
if (token.IsCancellationRequested)
{
token.ThrowIfCancellationRequested();
}
}
}
private void OnButton2Click(object sender, EventArgs eventArgs)
{
Guid identity = _taskMap.Count > 0 ? _taskMap.First().Value.Identity : default(Guid); // find some way to get the desired task
TaskTracker taskTracker;
if (_taskMap.TryGetValue(identity, out taskTracker))
{
taskTracker.TaskExiting += OnTaskExiting;
taskTracker.Stop();
}
}
private void OnTaskExiting(object sender, EventArgs eventArgs)
{
TaskTracker taskTracker = (TaskTracker)sender;
taskTracker.TaskExiting -= OnTaskExiting;
_taskMap.Remove(taskTracker.Identity);
Console.WriteLine("Time ellapsed for No partitioning at all version {0}ms , thread id was {1}", taskTracker.Stopwatch.ElapsedMilliseconds, Task.CurrentId);
}
private void OnButton3Click(object sender, EventArgs eventArgs)
{
Guid identity = _taskMap.Count > 0 ? _taskMap.First().Value.Identity : default(Guid); // find some way to get the desired task
TaskTracker taskTracker;
if (_taskMap.TryGetValue(identity, out taskTracker))
{
taskTracker.TaskExiting += OnTaskExiting;
taskTracker.Cancel();
}
}
這裏是向TaskTracker類:
public class TaskTracker
{
private readonly Action<CancellationToken> OnDoWork;
private readonly CancellationTokenSource TokenSource;
private readonly CancellationToken Token;
private bool _isRunning;
private Task _task;
public TaskTracker(Guid identity, Action<CancellationToken> onDoWork)
{
TokenSource = new CancellationTokenSource();
Token = TokenSource.Token;
Identity = identity;
OnDoWork = onDoWork;
}
public readonly Guid Identity;
public readonly Stopwatch Stopwatch = new Stopwatch();
public event EventHandler TaskExiting;
public void Start()
{
_isRunning = true;
_task = Task.Factory.StartNew(
() =>
{
Stopwatch.Start();
try
{
while (_isRunning)
{
OnDoWork(Token);
}
}
finally
{
Stopwatch.Stop();
if (TaskExiting != null)
{
TaskExiting(this, EventArgs.Empty);
}
}
}, Token
);
}
public void Stop(bool waitForTaskToExit = false)
{
if (_task == null)
{
throw new InvalidOperationException("Task hasn't been started yet");
}
_isRunning = false;
if (waitForTaskToExit)
{
_task.Wait();
}
_task = null;
}
public void Cancel()
{
if (_task == null)
{
throw new InvalidOperationException("Task hasn't been started yet");
}
_isRunning = false;
TokenSource.Cancel();
_task = null;
}
}
基本上,你的「工人」,你會檢查是否令牌表示它被取消,如果是的話,做一些清理工作,然後調用ThrowIfCancellationRequested on token來爆發。
謝謝@taylorjonl它就像一個魅力 – themis
有一點要提的是,即使任務停止,監控現在是可行的,在OnDoWork不會得到令牌,以阻止實際工作的工作。我會試圖弄明白,因爲任務沒有運行,正如我從觀察者那裏看到的那樣。如果我找不到它,我會發佈一個新問題,因爲這是一個新問題。再次感謝你 – themis