.NET的CancellationTokenSource和ManualResetEvent结合使用

一、CancellationTokenSource 是 C# 中的一个类,用于取消异步操作。它提供了一种机制,可以取消一个或多个异步操作。

CancellationTokenSource 包含以下主要方法:

  1. Cancel(): 该方法会取消所有挂起的操作,并引发 OperationCanceledException 异常。如果在调用 Cancel() 方法时没有挂起的操作,则没有任何效果。
  2. Cancel(boolean): 这个重载方法允许您取消一个或多个特定的挂起操作。如果Cancel(true)被调用,那么所有挂起的操作都将被取消,并引发 OperationCanceledException 异常。如果Cancel(false)被调用,那么不会有任何操作被取消。
  3. IsCancellationRequested: 这个属性会返回一个 bool 值,表明是否已经请求取消操作。如果已经请求取消操作,则返回 true;否则返回 false。
  4. ThrowIfCancellationRequested(): 这个方法会检查是否已经请求取消操作。如果是这样,那么会引发 OperationCanceledException 异常。

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时,通常需要以下步骤:

  1. 创建一个ManualResetEvent对象。可以通过构造函数来指定初始状态,如果初始状态为真,则线程可以继续执行;否则,线程将被阻塞直到事件被触发。
  2. 在需要等待某个事件发生的线程中,调用ManualResetEvent的WaitOne()方法。这将会阻塞当前线程,直到另一个线程调用ManualResetEvent的Set()方法触发事件。
  3. 在事件发生后,另一个线程可以调用ManualResetEvent的Set()方法来触发事件,这将使得等待的线程可以继续执行。
  4. 如果需要手动重置ManualResetEvent的状态,可以调用Reset()方法。这样,任何等待的线程将会继续被阻塞,直到再次调用Set()方法触发事件。

总之,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
{
    /// 
    /// 线程通用类
    /// 
    public class TaskCommand
    {
        //用于取消异步操作
        CancellationTokenSource tokenSource = new CancellationTokenSource();
        //用于在多线程编程中控制线程之间的通信
        ManualResetEvent resetEvent = new ManualResetEvent(true);
        Thread thread = null;

        /// 
        /// 队列对象
        /// 
        private Queue AsyncQueues { get; set; }

        /// 
        /// 并发任务数
        /// 
        private int ParallelTaskCount { get; set; }

        /// 
        /// 并行任务集合
        /// 
        private List ParallelTasks { get; set; }

        /// 
        /// 是否首次执行任务
        /// 
        private bool IsInitTask { get; set; }

        /// 
        /// 锁
        /// 
        private readonly object _objLock = new object();

        /// 
        /// 获取队列锁
        /// 
        private readonly object _queueLock = new object();

        /// 
        /// 开始任务
        /// 
        public void StartData()
        {
            tokenSource = new CancellationTokenSource();
            resetEvent = new ManualResetEvent(true);

            List Ids = new List();
            for (int i = 0; i < 10000; i++)
            {
                Ids.Add(i);
            }
            thread = new Thread(new ThreadStart(() => StartTask(Ids)));
            thread.Start();
        }

        /// 
        /// 暂停任务
        /// 
        public void OutData()
        {
            //task暂停
            resetEvent.Reset();
        }

        /// 
        /// 继续任务
        /// 
        public void ContinueData()
        {
            //task继续
            resetEvent.Set();
        }

        /// 
        /// 取消任务
        /// 
        public void Cancel()
        {
            //释放对象
            resetEvent.Dispose();
            foreach (var CurrentTask in ParallelTasks)
            {
                if (CurrentTask != null)
                {
                    if (CurrentTask.Status == TaskStatus.Running) { }
                    {
                        //终止task线程
                        tokenSource.Cancel();
                    }
                }
            }
            thread.Abort();
        }

        /// 
        /// 执行数据
        /// 
        /// 
        public void Execute(int Index)
        {
            //阻止当前线程
            resetEvent.WaitOne();

            Console.WriteLine("当前第" + Index + "个线程");

            Thread.Sleep(1000);
        }

        //控制线程并行数量
        public void StartTask(List Ids)
        {
            IsInitTask = true;
            ParallelTasks = new List();
            AsyncQueues = new Queue();
            //获取并发数
            ParallelTaskCount = 5;
            //初始化异步队列
            InitAsyncQueue(Ids);
            //开始执行队列任务
            HandlingTask();

            Task.WaitAll(new Task[] { Task.WhenAll(ParallelTasks.ToArray()) });
        }

        /// 
        /// 初始化异步队列
        /// 
        private void InitAsyncQueue(List Ids)
        {
            foreach (var item in Ids)
            {
                MeterInfo info = new MeterInfo();
                info.Id = item;
                AsyncQueues.Enqueue(new MeterAsyncQueue()
                {
                    MeterInfoTask = info
                });
            }
        }

        /// 
        /// 开始执行队列任务
        /// 
        private void HandlingTask()
        {
            lock (_objLock)
            {
                if (AsyncQueues.Count <= 0)
                {
                    return;
                }

                var loopCount = GetAvailableTaskCount();
                //并发处理队列
                for (int i = 0; i < loopCount; i++)
                {
                    HandlingQueue();
                }
                IsInitTask = false;
            }
        }

        /// 
        /// 处理队列
        /// 
        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);
                }
            }
        }

        /// 
        /// 获取当前有效并行的任务数
        /// 
        /// 
        [MethodImpl(MethodImplOptions.Synchronized)]
        private int GetAvailableTaskCount()
        {
            if (IsInitTask)
                return ParallelTaskCount;
            return 1;
        }
    }

    // 
    /// 并发对象
    /// 
    public class MeterAsyncQueue
    {
        public MeterAsyncQueue()
        {
            MeterInfoTask = new MeterInfo();
        }
 
        public MeterInfo MeterInfoTask { get; set; }
    }

    public class MeterInfo
    {
        public MeterInfo()
        {
 
        }
        public int Id { get; set; }
    }
}

你可能感兴趣的:(.net)