一、CancellationTokenSource 是 C# 中的一个类,用于取消异步操作。它提供了一种机制,可以取消一个或多个异步操作。
CancellationTokenSource 包含以下主要方法:
- Cancel(): 该方法会取消所有挂起的操作,并引发 OperationCanceledException 异常。如果在调用 Cancel() 方法时没有挂起的操作,则没有任何效果。
- Cancel(boolean): 这个重载方法允许您取消一个或多个特定的挂起操作。如果Cancel(true)被调用,那么所有挂起的操作都将被取消,并引发 OperationCanceledException 异常。如果Cancel(false)被调用,那么不会有任何操作被取消。
- IsCancellationRequested: 这个属性会返回一个 bool 值,表明是否已经请求取消操作。如果已经请求取消操作,则返回 true;否则返回 false。
- 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时,通常需要以下步骤:
- 创建一个ManualResetEvent对象。可以通过构造函数来指定初始状态,如果初始状态为真,则线程可以继续执行;否则,线程将被阻塞直到事件被触发。
- 在需要等待某个事件发生的线程中,调用ManualResetEvent的WaitOne()方法。这将会阻塞当前线程,直到另一个线程调用ManualResetEvent的Set()方法触发事件。
- 在事件发生后,另一个线程可以调用ManualResetEvent的Set()方法来触发事件,这将使得等待的线程可以继续执行。
- 如果需要手动重置ManualResetEvent的状态,可以调用Reset()方法。这样,任何等待的线程将会继续被阻塞,直到再次调用Set()方法触发事件。
总之,ManualResetEvent可以帮助线程间进行同步,使得线程可以等待另一个线程完成某个任务后才继续执行。文章来源:https://www.toymoban.com/news/detail-732188.html
3、通用类示例文章来源地址https://www.toymoban.com/news/detail-732188.html
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; }
}
}
到了这里,关于.NET的CancellationTokenSource和ManualResetEvent结合使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!