【发布时间】:2016-02-17 16:25:08
【问题描述】:
我有几个任务要执行。每个任务在不同的持续时间内完成其执行。一些任务执行数据库访问,其中一些只是进行一些计算。我的代码结构如下:
var Canceller = new CancellationTokenSource();
List<Task<int>> tasks = new List<Task<int>>();
tasks.Add(new Task<int>(() => { Thread.Sleep(3000); Console.WriteLine("{0}: {1}", DateTime.Now, 3); return 3; }, Canceller.Token));
tasks.Add(new Task<int>(() => { Thread.Sleep(1000); Console.WriteLine("{0}: {1}", DateTime.Now, 1); return 1; }, Canceller.Token));
tasks.Add(new Task<int>(() => { Thread.Sleep(2000); Console.WriteLine("{0}: {1}", DateTime.Now, 2); return 2; }, Canceller.Token));
tasks.Add(new Task<int>(() => { Thread.Sleep(8000); Console.WriteLine("{0}: {1}", DateTime.Now, 8); return 8; }, Canceller.Token));
tasks.Add(new Task<int>(() => { Thread.Sleep(6000); Console.WriteLine("{0}: {1}", DateTime.Now, 6); return 6; }, Canceller.Token));
tasks.ForEach(x => x.Start());
bool Result = Task.WaitAll(tasks.Select(x => x).ToArray(), 3000);
Console.WriteLine(Result);
Canceller.Cancel();
tasks.ToList().ForEach(x => { x.Dispose(); }); // Exception here
tasks.Clear();
tasks = null;
Canceller.Dispose();
Canceller = null;
我有 5 秒的时间来启动所有这些任务。我每 5 秒调用一次上面的代码。在下一次调用之前,我必须确保上一个执行期间没有任务剩余。假设执行后 3 秒后我想取消未完成任务的执行。
当我运行代码 Task.WaitAll 参数 3000 时,让前 3 个任务按预期完成。然后我得到Result 为false,因为还有两个其他任务没有完成。然后我必须取消这两个任务。如果我尝试处置它们,我会收到异常消息“只能处置处于已完成状态的任务。”
我怎样才能做到这一点?在我调用CancellationTokenSource 的Cancel 方法后,这两个任务仍然执行。这里有什么问题?
【问题讨论】:
-
将作业 (
Sleep(8000)) 拆分为多个部分 (Sleep(100) * 80) 并在开始每个部分之前检查IsCancelationRequest。