一、CancellationTokenSource 是 C# 中的一个类,用于取消异步操作。它提供了一种机制,可以取消一个或多个异步操作。
CancellationTokenSource 包含以下主要方法:
CancellationTokenSource 通常与 CancellationToken 一起使用。CancellationToken 是一个结构,它提供了一种机制,可以在异步操作中请求取消操作。CancellationTokenSource 可以生成一个 CancellationToken,这个 token 可以传递给异步操作,以便在需要取消操作时请求取消。
以下是一个简单的示例,演示如何使用 CancellationTokenSource 和 CancellationToken 来取消一个异步操作:
- CancellationTokenSource cts = new CancellationTokenSource();
- CancellationToken token = cts.Token;
-
- Task.Run(() =>
- {
- while (true)
- {
- token.ThrowIfCancellationRequested();
- // 异步操作代码...
- }
- }, cts.Token);
-
- // 在需要取消操作时调用以下方法:
- cts.Cancel();
在这个示例中,我们创建了一个 CancellationTokenSource 对象 cts 和一个与之关联的 CancellationToken 对象 token。我们将 CancellationToken 对象传递给 Task.Run 方法,以便在异步操作中检查是否请求了取消操作。如果取消操作被请求,则会引发 OperationCanceledException 异常,从而取消异步操作。在需要取消操作时,我们调用 cts.Cancel() 方法来请求取消操作。
二、ManualResetEvent是一种同步对象,用于在多线程编程中控制线程之间的通信。它允许一个或多个线程等待某个事件发生,然后在事件发生后继续执行。
使用ManualResetEvent时,通常需要以下步骤:
总之,ManualResetEvent可以帮助线程间进行同步,使得线程可以等待另一个线程完成某个任务后才继续执行。
3、通用类示例
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Runtime.CompilerServices;
-
- namespace Common
- {
- /// <summary>
- /// 线程通用类
- /// </summary>
- public class TaskCommand
- {
- //用于取消异步操作
- CancellationTokenSource tokenSource = new CancellationTokenSource();
- //用于在多线程编程中控制线程之间的通信
- ManualResetEvent resetEvent = new ManualResetEvent(true);
- Thread thread = null;
-
- /// <summary>
- /// 队列对象
- /// </summary>
- private Queue<MeterAsyncQueue> AsyncQueues { get; set; }
-
- /// <summary>
- /// 并发任务数
- /// </summary>
- private int ParallelTaskCount { get; set; }
-
- /// <summary>
- /// 并行任务集合
- /// </summary>
- private List<Task> ParallelTasks { get; set; }
-
- /// <summary>
- /// 是否首次执行任务
- /// </summary>
- private bool IsInitTask { get; set; }
-
- /// <summary>
- /// 锁
- /// </summary>
- private readonly object _objLock = new object();
-
- /// <summary>
- /// 获取队列锁
- /// </summary>
- private readonly object _queueLock = new object();
-
- /// <summary>
- /// 开始任务
- /// </summary>
- public void StartData()
- {
- tokenSource = new CancellationTokenSource();
- resetEvent = new ManualResetEvent(true);
-
- List<int> Ids = new List<int>();
- for (int i = 0; i < 10000; i++)
- {
- Ids.Add(i);
- }
- thread = new Thread(new ThreadStart(() => StartTask(Ids)));
- thread.Start();
- }
-
- /// <summary>
- /// 暂停任务
- /// </summary>
- public void OutData()
- {
- //task暂停
- resetEvent.Reset();
- }
-
- /// <summary>
- /// 继续任务
- /// </summary>
- public void ContinueData()
- {
- //task继续
- resetEvent.Set();
- }
-
- /// <summary>
- /// 取消任务
- /// </summary>
- public void Cancel()
- {
- //释放对象
- resetEvent.Dispose();
- foreach (var CurrentTask in ParallelTasks)
- {
- if (CurrentTask != null)
- {
- if (CurrentTask.Status == TaskStatus.Running) { }
- {
- //终止task线程
- tokenSource.Cancel();
- }
- }
- }
- thread.Abort();
- }
-
- /// <summary>
- /// 执行数据
- /// </summary>
- /// <param name="Index"></param>
- public void Execute(int Index)
- {
- //阻止当前线程
- resetEvent.WaitOne();
-
- Console.WriteLine("当前第" + Index + "个线程");
-
- Thread.Sleep(1000);
- }
-
- //控制线程并行数量
- public void StartTask(List<int> Ids)
- {
- IsInitTask = true;
- ParallelTasks = new List<Task>();
- AsyncQueues = new Queue<MeterAsyncQueue>();
- //获取并发数
- ParallelTaskCount = 5;
- //初始化异步队列
- InitAsyncQueue(Ids);
- //开始执行队列任务
- HandlingTask();
-
- Task.WaitAll(new Task[] { Task.WhenAll(ParallelTasks.ToArray()) });
- }
-
- /// <summary>
- /// 初始化异步队列
- /// </summary>
- private void InitAsyncQueue(List<int> Ids)
- {
- foreach (var item in Ids)
- {
- MeterInfo info = new MeterInfo();
- info.Id = item;
- AsyncQueues.Enqueue(new MeterAsyncQueue()
- {
- MeterInfoTask = info
- });
- }
- }
-
- /// <summary>
- /// 开始执行队列任务
- /// </summary>
- private void HandlingTask()
- {
- lock (_objLock)
- {
- if (AsyncQueues.Count <= 0)
- {
- return;
- }
-
- var loopCount = GetAvailableTaskCount();
- //并发处理队列
- for (int i = 0; i < loopCount; i++)
- {
- HandlingQueue();
- }
- IsInitTask = false;
- }
- }
-
- /// <summary>
- /// 处理队列
- /// </summary>
- private void HandlingQueue()
- {
- CancellationToken token = tokenSource.Token;
- lock (_queueLock)
- {
- if (AsyncQueues.Count > 0)
- {
- var asyncQueue = AsyncQueues.Dequeue();
-
- if (asyncQueue == null) return;
- var task = Task.Factory.StartNew(() =>
- {
- if (token.IsCancellationRequested)
- {
- return;
- }
- //阻止当前线程
- resetEvent.WaitOne();
- //执行任务
- Execute(asyncQueue.MeterInfoTask.Id);
-
- }, token).ContinueWith(t =>
- {
- HandlingTask();
- }, TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously);
- ParallelTasks.Add(task);
- }
- }
- }
-
- /// <summary>
- /// 获取当前有效并行的任务数
- /// </summary>
- /// <returns></returns>
- [MethodImpl(MethodImplOptions.Synchronized)]
- private int GetAvailableTaskCount()
- {
- if (IsInitTask)
- return ParallelTaskCount;
- return 1;
- }
- }
-
- // <summary>
- /// 并发对象
- /// </summary>
- public class MeterAsyncQueue
- {
- public MeterAsyncQueue()
- {
- MeterInfoTask = new MeterInfo();
- }
-
- public MeterInfo MeterInfoTask { get; set; }
- }
-
- public class MeterInfo
- {
- public MeterInfo()
- {
-
- }
- public int Id { get; set; }
- }
- }