所以我用一个样本试了一下:
var continuations = new List<Task>();
for (int i = 0; i < 20; i++) {
int counter = i;
var continuation = Task.Run(() => {
Console.WriteLine($"T{counter}: Start.");
Thread.Sleep(500);
Console.WriteLine($"T{counter}: Complete.");
}).ContinueWith(t => {
Console.WriteLine($"C{counter}: Start.");
Thread.Sleep(50);
Console.WriteLine($"C{counter}: Complete.");
});
continuations.Add(continuation);
}
Task.WaitAll(continuations.ToArray());
哪个输出以下内容 -暗示调度程序确实优先于启动新任务的延续(但这可以保证吗?):
T1: Start.
T2: Start.
T3: Start.
T0: Start.
T1: Complete.
T2: Complete.
T3: Complete.
C1: Start.
C3: Start.
T0: Complete.
C0: Start.
C2: Start.
C1: Complete.
T4: Start.
C3: Complete.
T5: Start.
C0: Complete.
T6: Start.
C2: Complete.
T7: Start.
T4: Complete.
C4: Start.
T5: Complete.
C5: Start.
T6: Complete.
C6: Start.
T7: Complete.
C7: Start.
C4: Complete.
C5: Complete.
T9: Start.
T8: Start.
C7: Complete.
T10: Start.
C6: Complete.
T11: Start.
T8: Complete.
C8: Start.
T9: Complete.
C9: Start.
T11: Complete.
C11: Start.
T10: Complete.
C10: Start.
C9: Complete.
C8: Complete.
T13: Start.
T12: Start.
C11: Complete.
T14: Start.
C10: Complete.
一个变种。在启动 Task 和注册 Continuation 之间,调用线程上还有额外的执行。
var continuations = new List<Task>();
for (int i = 0; i < 20; i++) {
int counter = i;
var task = Task.Run(() => {
Console.WriteLine($"T{counter}: Start.");
Thread.Sleep(500);
Console.WriteLine($"T{counter}: Complete.");
});
Thread.Sleep(100); // Do some stuff before registering continuation.
var continuation = task.ContinueWith(t => {
Console.WriteLine($"C{counter}: Start.");
Thread.Sleep(150);
Console.WriteLine($"C{counter}: Complete.");
});
continuations.Add(continuation);
}
Task.WaitAll(continuations.ToArray());
结果与上述情况相同,即任务 N 的继续被赋予其他排队任务的优先级。
T0: Start.
T1: Start.
T2: Start.
T3: Start.
T0: Complete.
C0: Start.
T1: Complete.
C1: Start.
C0: Complete.
T4: Start.
T2: Complete.
C2: Start.
C1: Complete.
T5: Start.
T3: Complete.
C3: Start.
C2: Complete.
T6: Start.
C3: Complete.
T7: Start.
T4: Complete.
C4: Start.
T5: Complete.
C5: Start.
C4: Complete.
T8: Start.
T6: Complete.
C6: Start.
C5: Complete.
T9: Start.
T7: Complete.
C7: Start.
C6: Complete.
T10: Start.
C7: Complete.
T11: Start.
T8: Complete.
C8: Start.
T9: Complete.
C9: Start.
C8: Complete.
T12: Start.
T10: Complete.
C10: Start.
C9: Complete.
T13: Start.
T11: Complete.
C11: Start.
T14: Start.
C10: Complete.
T15: Start.
C11: Complete.
T16: Start.
T12: Complete.
C12: Start.
T13: Complete.
C13: Start.
T14: Complete.
C14: Start.
C12: Complete.
T17: Start.
T15: Complete.
C15: Start.......
另一种变体。在注册延续之前,所有任务都首先在 scheuler 上排队(并且可以安排运行)。
const int taskCount = 20;
var tasks = new List<Task>();
for (int i = 0; i < taskCount; i++) {
int counter = i;
var task = Task.Run(() => {
Console.WriteLine($"T{counter}: Start.");
Thread.Sleep(500);
Console.WriteLine($"T{counter}: Complete.");
});
tasks.Add(task);
}
Thread.Sleep(400);
var continuations = new List<Task>();
for (int i = 0; i < taskCount; i++) {
int counter = i;
var continuation = tasks[i].ContinueWith(t => {
Console.WriteLine($"C{counter}: Start.");
Thread.Sleep(150);
Console.WriteLine($"C{counter}: Complete.");
});
continuations.Add(continuation);
}
Task.WaitAll(continuations.ToArray());
结果和以前一样 - 延续优先。
T0: Start.
T2: Start.
T3: Start.
T1: Start.
T1: Complete.
T3: Complete.
T0: Complete.
T2: Complete.
C2: Start.
C0: Start.
C3: Start.
C1: Start.
C2: Complete.
C1: Complete.
C0: Complete.
C3: Complete.
T7: Start.
T4: Start.
T6: Start.
T5: Start.
T6: Complete.
T5: Complete.
T7: Complete.
T4: Complete.
C6: Start.
C5: Start.
C7: Start.
C4: Start.
C7: Complete.
T8: Start.
C5: Complete.
T9: Start.
C6: Complete.
T10: Start.
C4: Complete.
T11: Start.
T8: Complete.
C8: Start.
T10: Complete.
C10: Start.
T9: Complete.
C9: Start.
T11: Complete.
C11: Start.
C8: Complete.
T12: Start.
C9: Complete.
T13: Start.
C10: Complete.
T14: Start.
C11: Complete.
T15: Start.
T14: Complete.
T12: Complete.
C12: Start.
T13: Complete.
C13: Start.
C14: Start.
T15: Complete.
C15: Start.
T16: Start.
C12: Complete.
C13: Complete.
T18: Start.
T17: Start.
C14: Complete.
T19: Start.
C15: Complete.
T16: Complete.
C16: Start.
T18: Complete.
C18: Start.
T17: Complete.
T19: Complete.
C19: Start.
C16: Complete.
C17: Start.
C18: Complete.
C19: Complete.
C17: Complete.