上图的所有多线程案例大全完整版本项目源代码下载---->点击下载
在C#开发过程中,我们有时需要取消正在运行的task,这可能有多种原因。
- 任务未正确初始化或从未启动:如果你的task从未启动,或者在启动之前未正确初始化,那么在尝试取消它时可能会遇到问题。解决方案是确保你的task已经正确地初始化并启动。
- 任务取消事件丢失或未触发:C#的
Task
类有一个CancellationToken
属性,它可以用来取消任务。如果你没有正确地设置或触发这个取消事件,可能会导致任务无法被取消。解决方案是确保在适当的时候调用CancellationToken.ThrowIfCancellationRequested()
方法。 - 任务运行时间过长:如果任务运行时间过长,可能无法在需要取消时立即响应取消请求。解决方案是考虑使用超时或其他方式来判断任务是否可以安全地取消。
- 线程阻塞或等待资源释放:如果任务在等待某些资源(如锁)或在等待其他线程完成时被取消,可能会导致问题。解决方案是确保在取消任务之前,所有必要的资源都已经释放。
- 线程安全问题:如果任务中有共享状态或资源,并且没有正确地处理线程安全问题,可能会导致取消任务时出现异常。解决方案是确保你的代码是线程安全的,特别是当多个线程可能同时访问和修改共享资源时。
- 异步操作错误处理:如果在异步操作中使用了错误处理,而没有考虑到取消任务的情况,可能会导致问题。解决方案是在处理错误时检查任务的取消状态,如果任务被取消,可以抛出适当的异常。
- 任务取消通知丢失或未传递:如果任务取消通知丢失或未传递到其他相关的组件或线程,可能会导致问题。解决方案是确保在适当的时候触发和传递任务取消通知。
在C#中,可以使用CancellationToken
来取消一个任务(Task
)。下面是一种常见的方法:
private void button23_Click(object sender, EventArgs e)
{
try
{
TaskFactory taskFactory = new TaskFactory();
List<Task> list = new List<Task>();
CancellationTokenSource cts = new CancellationTokenSource();
for (int i = 0; i < 30; i++)
{
string name = $"当前运行第个-->{i}";
Action<object> acitn = t =>
{
//在每个委托里面开始和结束添加try catch,建议这样处理,即可以异步,还不卡界面
try
{
Thread.Sleep(Math.Abs(Guid.NewGuid().GetHashCode() % 1000) + 1000);
if (t.ToString().Equals("当前运行第个-->2") || t.ToString().Equals("当前运行第个-->5"))
{
throw new Exception(string.Format($"{t}运行失败,线程{Thread.CurrentThread.ManagedThreadId}"));
}
if (cts.IsCancellationRequested)
{
Console.WriteLine("{0}放弃执行,线程{1}", t, Thread.CurrentThread.ManagedThreadId);
}
Console.WriteLine("{0}执行成功,线程{1}", t, Thread.CurrentThread.ManagedThreadId);
}
catch (Exception ex) //AggregateException这个是收集多线程的错误信息
{
cts.Cancel();
Console.WriteLine(ex.Message);
}
};
list.Add(taskFactory.StartNew(acitn, name, cts.Token));
}
Task.WaitAll(list.ToArray()); //必须等待结束
}
catch (AggregateException aex) //AggregateException这个是收集多线程的错误信息
{
foreach (var item in aex.InnerExceptions)
{
Console.WriteLine(item.Message);
}
}
}