C#中的多线程和取消令牌
本文关键字:取消 令牌 多线程 | 更新日期: 2023-09-27 18:12:21
我是多线程的新手,花了几天时间调试这个程序,但运气不佳。在进行生产之前,我正在尝试进行概念验证。
我有一个自定义对象的列表。它们的属性是Task类型的T和int类型的Timeout。为了演示的目的,我确实创建了两个简单的任务,他们做简单的事情
public class Program
{
public static void Main(string[] args)
{
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
CancellationToken cancellationToken = cancellationTokenSource.Token;
List<MyItem> myItems = new List<MyItem>();
myItems.Add(createtask1(2000,1000,cancellationToken)); // this task should run for one second....result: should timeout
myItems.Add(createtask2(2000,3000,cancellationToken));// this task should run for two second....result: should NOT timeout
Parallel.ForEach(myItems,(item)=>{
Task task = item.T;
// start the task
task.Start();
Console.WriteLine("waiting for the task with timeout:{0} to finish", item.Timeout);
try{
bool hasNotTimedOut = task.Wait(item.Timeout);
if (hasNotTimedOut)
{
Console.WriteLine("Task with timeout: {0}, has not timed out", item.Timeout);
}
else
{
Console.WriteLine("Task with timeout: {0}, has timed out", item.Timeout);
cancellationTokenSource.Cancel();
Console.WriteLine("Status of the task with timeout: {0} is {1}", item.Timeout,task.Status.ToString());
}
}
catch (AggregateException ex)
{
if (ex.InnerException is OperationCanceledException)
{
Console.WriteLine("Status of the task with timeout: {0} is {1}5", item.Timeout,task.Status.ToString());
}
else
Console.WriteLine(ex);
}
});
// Task.WaitAll(myItems.Select(item=>item.T).ToArray());
Console.WriteLine("End of Main");
}
private static MyItem createtask1(int delayTime, int timeout,CancellationToken cancellationToken)
{
MyItem toReturn = new MyItem();
toReturn.Timeout = timeout;
toReturn.T = new Task(()=>{
Console.WriteLine("Task1 is getting executed with DelayTime:{0}, timeout:{1}",delayTime,timeout);
Task.Delay(delayTime).Wait();
Console.WriteLine("Task1 finished executing with DelayTime:{0}, timeout:{1}",delayTime,timeout);
cancellationToken.ThrowIfCancellationRequested();
},cancellationToken);
return toReturn;
}
private static MyItem createtask2(int delayTime, int timeout,CancellationToken cancellationToken)
{
MyItem toReturn = new MyItem();
toReturn.Timeout = timeout;
toReturn.T = new Task(()=>{
Console.WriteLine("Task2 is getting executed with DelayTime:{0}, timeout:{1}",delayTime,timeout);
Task.Delay(delayTime).Wait();
Console.WriteLine("Task2 finished executing with DelayTime:{0}, timeout:{1}",delayTime,timeout);
cancellationToken.ThrowIfCancellationRequested();
},cancellationToken);
return toReturn;
}
}
public class MyItem{
public Task T{get;set;}
public int Timeout{get;set;}
}
它似乎试图取消最后一项任务,但在我的情况下,应该取消第一项任务。如果我不包括CancellationToken,我的代码会很好地工作,即它会告诉我什么任务超时。
你能告诉我我做错了什么吗
仅仅因为您将CancellationToken作为参数传递给Task,然后取消该Token,Task仍然不会被取消。您需要检查函数内部的Token,并在请求时手动取消Task。
CancellationToken可以传递给实现该系统的Task.Delay()
。
像这样:
private static MyItem createtask1(int delayTime, int timeout, CancellationToken cancellationToken)
{
MyItem toReturn = new MyItem();
toReturn.Timeout = timeout;
toReturn.T = new Task(() => {
Console.WriteLine("Task1 is getting executed with DelayTime:{0}, timeout:{1}", delayTime, timeout);
Task.Delay(delayTime, cancellationToken).Wait();
Console.WriteLine("Task1 finished executing with DelayTime:{0}, timeout:{1}", delayTime, timeout);
cancellationToken.ThrowIfCancellationRequested();
}, cancellationToken);
return toReturn;
}
此外,您不需要cancellationToken.ThrowIfCancellationRequested();
,因为等待Task.Delay()
会在取消时引发异常。