是否重载版本的Task.WaitAny取消任务?

Rot*_*eel 6 c# multithreading

int WaitAny(Task[] tasks, int millisecondsTimeout); 
Run Code Online (Sandbox Code Playgroud)

上述方法是否在超时后取消了该任务?看起来它没有,但C#70-483考试参考书说这个重载版本取消任务.这是一些测试代码,

Task longRunning = Task.Run(() =>
{
    Thread.Sleep(10000);
});
int index = Task.WaitAny(new Task[] { longRunning }, 1000); // returns -1
index = 0; // reset it to reuse in the loop
while (index < 12)
{
    Thread.Sleep(1000);
    index++;
    Console.WriteLine("long running task status {0}", longRunning.Status);
}
Run Code Online (Sandbox Code Playgroud)

前几次,状态正在运行,之后状态更改为RanToCompletion.那么那个超时与Task和WaitAny有什么关系呢?

spe*_*der 3

Task.WaitAny如果 (a) 它包装的任何任务完成或 (b) 超过超时,则将完成。如果超过超时,则WaitAny完成,但它包装的任务不会被取消。任务的取消往往是合作性的而不是隐式的,并且将涉及显式传递CancellationToken.

如果您希望任务在超时后取消,您可以创建一个CancellationTokenSource超时并将其传递给您正在等待的任务:

 using(CancellationTokenSource cts=new CancellationTokenSource(TimeSpan.FromSeconds(5)))
{
    var task = Task.Delay(TimeSpan.FromSeconds(10), cts.Token);
    task.Wait();
}
Run Code Online (Sandbox Code Playgroud)

当然,强烈建议不要使用阻塞方法等待任务完成,就像包装同步阻塞代码Task.Run并期望一切正常且“异步”地工作一样。

拥抱异步/等待以获得胜利。