通常我不会发布一个带有答案的问题,但这次我想吸引一些关注,因为我认为这可能是一个模糊但普遍存在的问题。它是由 这个问题触发的,自那时以来,我审查了自己的旧代码,并发现其中一些也受到了影响。
下面的代码启动并等待两个任务task1
和task2
,它们几乎相同。 task1
与 task2
的唯一区别在于它运行一个永不停歇的循环。在我看来,这两种情况对于执行 CPU-bound 工作的某些实际场景非常典型。
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication
{
public class Program
{
static async Task TestAsync()
{
var ct = new CancellationTokenSource(millisecondsDelay: 1000);
var token = ct.Token;
// start task1
var task1 = Task.Run(() =>
{
for (var i = 0; ; i++)
{
Thread.Sleep(i); // simulate work item #i
token.ThrowIfCancellationRequested();
}
});
// start task2
var task2 = Task.Run(() =>
{
for (var i = 0; i < 1000; i++)
{
Thread.Sleep(i); // simulate work item #i
token.ThrowIfCancellationRequested();
}
});
// await task1
try
{
await task1;
}
catch (Exception ex)
{
Console.WriteLine(new { task = "task1", ex.Message, task1.Status });
}
// await task2
try
{
await task2;
}
catch (Exception ex)
{
Console.WriteLine(new { task = "task2", ex.Message, task2.Status });
}
}
public static void Main(string[] args)
{
TestAsync().Wait();
Console.WriteLine("Enter to exit...");
Console.ReadLine();
}
}
}
这里是小提琴 的代码。输出结果:
{ task = task1, Message = 操作已取消,Status = 已取消 } { task = task2, Message = 操作已取消,Status = 已故障 }
为什么task1
的状态是已取消
,而task2
的状态是已故障
?请注意,在两种情况下,我都没有将token
作为第二个参数传递给Task.Run
。