我有一个多线程应用程序,我需要在一定时间后取消每个任务,即使在取消时,它们使用非托管资源。现在我使用以下代码(例如控制台应用程序)。在实际应用中,延迟可能发生在非托管资源中。
static void Main()
{
for (int i = 0; i < 10; i++)
{
Task.Factory.StartNew(Do, TaskCreationOptions.LongRunning);
}
Console.ReadLine();
}
private static void Do()
{
new Timer(Thread.CurrentThread.Abort, null, 1000, -1);
try
{
Console.WriteLine("Start " + Task.CurrentId);
Thread.Sleep(2000);
Console.WriteLine("End " + Task.CurrentId);
}
catch (Exception)
{
Console.WriteLine("Thread Aborted " + Task.CurrentId);
}
}
得到结果:
![enter image description here](https://i.stack.imgur.com/23XX6.jpg)
但从安全的角度来看,我不确定这是否适合实际应用。
我还在不同的变体中使用了 CancellationToken ,但它没有给我正确的结果,因为当我使用 CancellAfter() 或 .Delay() 与时间跨度并在一定时间后取消任务时,我得到了以下结果:
static void Main()
{
for (int i = 0; i < 10; i++)
{
var clt = new CancellationTokenSource();
Task task = new Task(() =>
{
Task.Delay(2000).ContinueWith(_ =>
{
clt.Cancel();
}, clt.Token);
Do(clt.Token);
}, clt.Token);
task.Start();
}
Console.ReadLine();
}
private static void Do(CancellationToken cltToken)
{
Console.WriteLine("Start " + Task.CurrentId);
Thread.Sleep(2500);
if (!cltToken.IsCancellationRequested)
{
Console.WriteLine("End " + Task.CurrentId);
}
else
{
Console.WriteLine("Cancelled "+ Task.CurrentId);
}
}
![enter image description here](https://i.stack.imgur.com/FUy0O.jpg)
在这种情况下,必须取消所有任务,因为 Thread.Sleep() > 分配给执行每个任务的时间。但我们可以看到有的时候执行了。
我还使用以下构造并给出相同的结果:
static void Main()
{
for (int i = 0; i < 10; i++)
{
var clt = new CancellationTokenSource();
clt.CancelAfter(2000);
Task.Factory.StartNew(Do, clt.Token);
}
Console.ReadLine();
}
private static void Do(object obj)
{
var cltToken = (CancellationToken) obj;
Console.WriteLine("Start " + Task.CurrentId);
Thread.Sleep(2500);
if (!cltToken.IsCancellationRequested)
{
Console.WriteLine("End " + Task.CurrentId);
}
else
{
Console.WriteLine("Cancelled "+ Task.CurrentId);
}
}
![enter image description here](https://i.stack.imgur.com/9ZdpM.jpg)
我还使用 Parallel 并初始化 Cancellation Token Inside 方法 Do(),并使用 Timer 在时间跨度后取消令牌,但都给出相同的结果。
那么,为什么会发生这种情况以及在一段时间后取消任务的正确方法是什么???