并发任务管理器AsyncTaskManager
//--------------------------------------------------------------------------
//
// Copyright (c) BUSHUOSX. All rights reserved.
//
// File: AsyncTaskManager.cs
//
// Version:1.1.0.6
//
// Datetime:20170813
//
//-------------------------------------------------------------------------- using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks; namespace BUSHUOSX
{
class AsyncTaskManager
{
/// <summary>
/// 缓存的任务队列
/// </summary>
readonly Queue<Task> _taskQueue = new Queue<Task>(); /// <summary>
/// 工作锁,保护_taskQueue
/// </summary>
SpinLock _workLock; /// <summary>
/// 工作信号,与MaxConcurrencyLevel控制并行量
/// </summary>
SemaphoreSlim _workSemaphore; /// <summary>
/// 工作线程取消标志
/// </summary>
CancellationTokenSource _ctsCancel;
/// <summary>
/// 工作器每次启动的工作时限
/// </summary>
int _timeoutMillisecond;
/// <summary>
/// 工作线程
/// </summary>
Task _worker; /// <summary>
/// 工作器状态
/// </summary>
private bool IsWorking { get; set; } /// <summary>
/// 任务最大并发量
/// </summary>
public int MaxConcurrencyLevel { get; } /// <summary>
/// 内部工作器将在队列中有任务时自动启动。否则由Start方法启动。
/// </summary>
public bool AutoRunWorker { get; } /// <summary>
/// 队列中的任一任务完成时,都将调用
/// </summary>
private Action<Task> _callbackOnAnyTaskComplited; /// <summary>
/// 控制异步任务的并发量。
/// 注意:只能严格控制stauts为Created的任务
/// </summary>
/// <param name="maxConcurrencyLevel">最大并发数。小于等于0时设置为int.MaxValue</param>
/// <param name="callbackOnAnyTaskComplited">不为null时,队列中的任一任务完成后都将传递给此回调方法</param>
/// <param name="autoRunWorker">指示内部工作器是在内部队列排入任务时自动启动,还是由Start方法启动。</param>
/// <param name="timeout">调度完所有任务的时限。小于等于0时不设置超时</param>
public AsyncTaskManager(int maxConcurrencyLevel, Action<Task> callbackOnAnyTaskComplited = null, bool autoRunWorker = true, int timeoutMillisecond = )
{
_callbackOnAnyTaskComplited = callbackOnAnyTaskComplited;
AutoRunWorker = autoRunWorker;
MaxConcurrencyLevel = maxConcurrencyLevel <= ? int.MaxValue : maxConcurrencyLevel;
_timeoutMillisecond = timeoutMillisecond <= ? : timeoutMillisecond;
} /// <summary>
/// 排入一个任务到内部队列,该队列中的任务将被依次调用。
/// </summary>
/// <param name="task">要排队的任务。注意:只能严格控制stauts为Created的任务</param>
/// <param name="callbackOnTaskComplited">task任务完成时回调。如果所有任务使用同样的回调方法,建议使用构造函数中的callbackOnAnyTaskComplited</param>
public void QueueTask(Task task, Action<Task> callbackOnTaskComplited = null)
{
if (task == null) return;
if (null == callbackOnTaskComplited)
{
EnqueueTask(task);
}
else
{
EnqueueTask(task.ContinueWith(callbackOnTaskComplited));
}
if (AutoRunWorker)
{
notifyStartWork();
}
} /// <summary>
/// 枚举任务到内部队列,该队列中的任务将被依次调用。
/// </summary>
/// <param name="tasks">要排队的任务。注意:只能严格控制stauts为Created的任务</param>
/// <param name="callbackOnTaskComplited">tasks中的每个任务完成时回调</param>
public void QueueTask(IEnumerable<Task> tasks, Action<Task> callbackOnTaskComplited = null)
{
foreach (var item in tasks)
{
if (item == null) break;
if (null == callbackOnTaskComplited)
{
EnqueueTask(item);
}
else
{
EnqueueTask(item.ContinueWith(callbackOnTaskComplited));
}
}
if (AutoRunWorker)
{
notifyStartWork();
}
} /// <summary>
/// 返回此刻队列中的任务。
/// </summary>
/// <returns></returns>
public Task[] GetQueueTask()
{
bool gotlock = false;
try
{
_workLock.Enter(ref gotlock);
if (_taskQueue.Count > )
{
return _taskQueue.ToArray();
}
else
{
return null;
}
}
finally
{
if (gotlock) _workLock.Exit();
}
} /// <summary>
/// 启动内部工作器。
/// 注意:为降低资源占用,该工作器在内部队列为空时会自动退出。
/// </summary>
public void Start()
{
notifyStartWork();
} /// <summary>
/// 阻塞线程,等待内部工作器运行结束
/// </summary>
/// <returns>RanToCompletion:所有队列任务已被调度。Canceled:手动取消或挂起了任务,或任务超时。Faulted:未知错误。</returns>
public TaskStatus WaitTaskSchdulerComplited()
{
if (_worker == null) throw new NotSupportedException("_worker is null");
try
{
_worker.Wait();
}
catch (Exception)
{
}
return _worker.Status;
} /// <summary>
/// 挂起队列中剩余的任务。稍后可以使用Continue方法继续。
/// </summary>
public void Suspend()
{
stopWorkThread(false);
} /// <summary>
/// 停止工作器,并清空内部任务队列还未调用的任务。
/// 已调用的任务还将继续运行。
/// </summary>
public void Cancel()
{
stopWorkThread(true);
} /// <summary>
/// 停止工作器
/// </summary>
/// <param name="clearTasks">true时清空内部任务队列</param>
private void stopWorkThread(bool clearTasks)
{
if (IsWorking)
{
_ctsCancel.Cancel();
if (clearTasks)
{
bool gotlock = false;
try
{
_workLock.Enter(ref gotlock);
_taskQueue.Clear();
}
finally
{
if (gotlock) _workLock.Exit();
}
}
}
} /// <summary>
/// 继续之前挂起的任务。
/// </summary>
public void Continue()
{
notifyStartWork();
} /// <summary>
/// 内部启动工作器
/// </summary>
private void notifyStartWork()
{
if (IsWorking) return; //初始化
_ctsCancel = new CancellationTokenSource();
if (_timeoutMillisecond > )
{
_ctsCancel.CancelAfter(_timeoutMillisecond);
}
_workLock = new SpinLock();
_workSemaphore = new SemaphoreSlim(MaxConcurrencyLevel, MaxConcurrencyLevel); _worker = Task.Run(new Action(workerThread), _ctsCancel.Token);
} /// <summary>
/// 任一任务完成时调用
/// </summary>
/// <param name="task"></param>
private void anyTaskComplited(Task task)
{
_workSemaphore.Release();
//todo task
_callbackOnAnyTaskComplited?.Invoke(task);
//Debug.WriteLine("完成任务{0}:{1}", task.Id, task.Status.ToString());
} /// <summary>
/// 工作器线程执行方法。只应存在一个。
/// </summary>
private void workerThread()
{
IsWorking = true;
Debug.WriteLine("工作线程启动……");
try
{
Task tmp = null;
while (true)
{
#if DEBUG
//不恰当的操作,只为屏蔽调试时错误
//会导致_worker状态为RanToCompletion
try
{
_workSemaphore.Wait(_ctsCancel.Token);
}
catch (OperationCanceledException)
{
//_ctsCancel.Token.ThrowIfCancellationRequested();
return;
}
#else
_workSemaphore.Wait(_ctsCancel.Token); //传递取消状态
_ctsCancel.Token.ThrowIfCancellationRequested();
#endif tmp = DequeueTask();
if (tmp != null)
{
if (tmp.Status == TaskStatus.Created)
{
tmp.Start();
}
tmp.ContinueWith(anyTaskComplited);
}
else
{
if (_taskQueue.Count == )
{
Debug.WriteLine("workerAsync:taskQueue is empty");
break;
}
}
}
}
finally
{
//notifyEndWork();
IsWorking = false;
Debug.WriteLine("工作线程结束……");
}
} /// <summary>
/// 排入任务,期望线程安全
/// </summary>
/// <param name="task"></param>
private void EnqueueTask(Task task)
{
bool gotlock = false;
try
{
_workLock.Enter(ref gotlock);
_taskQueue.Enqueue(task);
}
finally
{
if (gotlock) _workLock.Exit();
} } /// <summary>
/// 弹出任务,期望线程安全
/// </summary>
/// <returns></returns>
private Task DequeueTask()
{
bool gotlock = false;
try
{
_workLock.Enter(ref gotlock);
if (_taskQueue.Count > )
{
return _taskQueue.Dequeue();
}
else
{
return null;
}
}
finally
{
if (gotlock) _workLock.Exit();
}
}
}
}
并发任务管理器AsyncTaskManager的更多相关文章
- 如何配置IIS处理多并发请求及存在的问题
很多时候多线程能快速高效独立的计算数据,应用比较多. 但今天遇到的多进程下的问题更是让人觉得复杂 多进程下static变量都要失效,就目前的平台和产品static使用是很多的,各种session.ca ...
- mmysql-最大链接数和最大并发数的区别
关于连接数和并发数的设置(针对Innodb引擎) 对于机器本身来说,进程数是说机器正在运行的进程数量,调出任务管理器就可以看到.连接数是指进程接收和发送数据的连接ip的数量.并发数是指进程同时发送数据 ...
- Visual Studio并发Qpar优化效果
IOCP客户端的connect线程FOR循环中添加强制并行,1万/S并发connect+send+recv+close,任务管理器使用从60%降到20%. Visual Studio性能监控CPU使用 ...
- IIS处理并发请求时出现的问题及解决
一个ASP.NET项目在部署到生产环境时,当用户并发量达到200左右时,IIS出现了明显的请求排队现象,发送的请求都进入等待,无法及时响 应,系统基本处于不可用状态.因经验不足,花了很多时间精力解决这 ...
- java线程与并发(一)
有好几个月没写博客了,各种破事儿忙完,决定继续写博客,恰好最近想了解下有关Java并发的一些知识,所以就准备这一段时间,用零碎的时间多记录一点有关并发的知识.希望这次能一直坚持下去. 想了解并发,必须 ...
- Java并发编程:如何创建线程?
Java并发编程:如何创建线程? 在前面一篇文章中已经讲述了在进程和线程的由来,今天就来讲一下在Java中如何创建线程,让线程去执行一个子任务.下面先讲述一下Java中的应用程序和进程相关的概念知识, ...
- Java多线程中的进程,线程,并行,并发
2:什么是进程? 通过任务管理器我们就看到了进程的存在. 而通过观察,我们发现只有运行的程序才会出现进程. 进程:就是正在运行的程序. 进程是系统进行资源分配和调用的独立单位.每一个进程都有它自己的内 ...
- Java并发编程:线程和进程的创建(转)
Java并发编程:如何创建线程? 在前面一篇文章中已经讲述了在进程和线程的由来,今天就来讲一下在Java中如何创建线程,让线程去执行一个子任务.下面先讲述一下Java中的应用程序和进程相关的概念知识, ...
- python并发编程之多进程一
一,什么是进程 进程是操作系统结构的基础:是一个正在执行的程序:计算机中正在运行的程序实例:可以分配给处理器并由处理器执行的一个实体: 二,进程与程序的区别 进程即运行中的程序,从中即可知,进程是在运 ...
随机推荐
- 蓝牙BLE4.0的LL层数据和L2CAP层数据的区分与理解
一直搞不太清楚蓝牙BLE协议,不知道LL层和L2CAP层是如何划分的,后来博士给我讲了讲就理解了,写下来,做个记录: 1. 我们知道,除了蓝牙5.1新出的CTE,所有的BLE都是如下类型的包: 对于连 ...
- web.xml的加载过程是context-param >> listener >> fileter >> servlet
web.xml的加载过程是context-param >> listener >> fileter >> servlet
- MATLAB 中gcf、gca 以及gco 的区别
MATLAB 中gcf.gca 以及gco 的区别gcf 返回当前Figure 对象的句柄值gca 返回当前axes 对象的句柄值gco 返回当前鼠标单击的句柄值,该对象可以是除root 对象外的任意 ...
- 二十八、详述 IntelliJ IDEA 远程调试 Tomcat 的方法
在调试代码的过程中,为了更好的定位及解决问题,有时候需要我们使用远程调试的方法.在本文中,就让我们一起来看看,如何利用 IntelliJ IDEA 进行远程 Tomcat 的调试. 首先,配置remo ...
- POJ 1644 分苹果 (递归解法)
把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法. Input 第一行是测试数据的数目t(0 <= t < ...
- Objective-C中的@dynamic与@synthesize的区别
Objective-C中的@dynamic 转自:http://blog.csdn.net/haishu_zheng/article/details/12873151 一.@dynamic与@synt ...
- sharepoint OOS巨大坑
首先,我们安装的操作系统是windows server 2016 datacenter最新版,然后安装了OOS2016年的那个版本,打好语言包,安装必备软件,所有的步骤都没问题,但是你配置OOS场的时 ...
- 【Linux资源管理】一款优秀的linux监控工具——nmon
(一)nmon工具概述 nmon是以一个用来做linux服务器监控的工具,通过nmon,可以实现对以下参数的监控: --CPU使用率 --内存.交换空间使用率 --网络使用情况 --磁盘I/O,读写速 ...
- kendo UI 倒如css 和 js 后 窗口控件上的工具栏图标不显示如何解决
examples 文档中找到window的例子打开一个 查看其中文件引入 <head> <title>API</title> <meta char ...
- C++笔记006:关于类的补充
原创笔记,转载请注明出处! 点击[关注],关注也是一种美德~ 关于类的补充: 类是一个数据类型(固定大小内存块的别名),定义一个类,是一个抽象的概念,不会给你分配内存,用数据类型定义变量的时候,才会分 ...