//--------------------------------------------------------------------------
//
// 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的更多相关文章

  1. 如何配置IIS处理多并发请求及存在的问题

    很多时候多线程能快速高效独立的计算数据,应用比较多. 但今天遇到的多进程下的问题更是让人觉得复杂 多进程下static变量都要失效,就目前的平台和产品static使用是很多的,各种session.ca ...

  2. mmysql-最大链接数和最大并发数的区别

    关于连接数和并发数的设置(针对Innodb引擎) 对于机器本身来说,进程数是说机器正在运行的进程数量,调出任务管理器就可以看到.连接数是指进程接收和发送数据的连接ip的数量.并发数是指进程同时发送数据 ...

  3. Visual Studio并发Qpar优化效果

    IOCP客户端的connect线程FOR循环中添加强制并行,1万/S并发connect+send+recv+close,任务管理器使用从60%降到20%. Visual Studio性能监控CPU使用 ...

  4. IIS处理并发请求时出现的问题及解决

    一个ASP.NET项目在部署到生产环境时,当用户并发量达到200左右时,IIS出现了明显的请求排队现象,发送的请求都进入等待,无法及时响 应,系统基本处于不可用状态.因经验不足,花了很多时间精力解决这 ...

  5. java线程与并发(一)

    有好几个月没写博客了,各种破事儿忙完,决定继续写博客,恰好最近想了解下有关Java并发的一些知识,所以就准备这一段时间,用零碎的时间多记录一点有关并发的知识.希望这次能一直坚持下去. 想了解并发,必须 ...

  6. Java并发编程:如何创建线程?

    Java并发编程:如何创建线程? 在前面一篇文章中已经讲述了在进程和线程的由来,今天就来讲一下在Java中如何创建线程,让线程去执行一个子任务.下面先讲述一下Java中的应用程序和进程相关的概念知识, ...

  7. Java多线程中的进程,线程,并行,并发

    2:什么是进程? 通过任务管理器我们就看到了进程的存在. 而通过观察,我们发现只有运行的程序才会出现进程. 进程:就是正在运行的程序. 进程是系统进行资源分配和调用的独立单位.每一个进程都有它自己的内 ...

  8. Java并发编程:线程和进程的创建(转)

    Java并发编程:如何创建线程? 在前面一篇文章中已经讲述了在进程和线程的由来,今天就来讲一下在Java中如何创建线程,让线程去执行一个子任务.下面先讲述一下Java中的应用程序和进程相关的概念知识, ...

  9. python并发编程之多进程一

    一,什么是进程 进程是操作系统结构的基础:是一个正在执行的程序:计算机中正在运行的程序实例:可以分配给处理器并由处理器执行的一个实体: 二,进程与程序的区别 进程即运行中的程序,从中即可知,进程是在运 ...

随机推荐

  1. UVa 1395 - Slim Span(最小生成树变形)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  2. angular.js和ionic框架搭建一个webApp

    原文地址:http://www.jianshu.com/p/ea0dcf1d31c9

  3. Arduino 入门之小星星

    原理:通过编号映射不同的频率音频信号,配合延时输出,达到演奏音乐和跑马灯的效果. 优酷视频链接:https://v.youku.com/v_show/id_XMzcxODQ4NjA3Mg==.html ...

  4. 启动memcache

    "D:\SOFT\memcached-1.4.5-amd64\memcached-amd64\memcached.exe"

  5. 十一、IntelliJ IDEA 中的版本控制介绍(上)

    咱们已经了解了很多关于 IntelliJ IDEA 的使用方法,至少可以独立的运用 IntelliJ IDEA 进行项目开发啦!但是一个人进行项目开发更趋向于理想化,更多的则是团队协同开发.这时,咱们 ...

  6. IE下内容居中

    ie8下调了很长时间的居中问题,加一个body {text-align:center;},居然解决了.. 参考解决答案:*html * {margin:0px; padding:0;} 然后在盒子里b ...

  7. 入门——Bootstrap栅格系统

    作为刚接触到Bootstrap框架的新手一枚,刚开始对Bootstrap中的栅格系统一脸懵逼,后来经过反复的上网查找资料以及自己一直在练习,总算对栅格系统了解个差不多,所以我将我所了解的当成是日记写下 ...

  8. Spring入门第二课:Spring配置Bean的细节

    1.配置bean的作用域: 通过配置scope属性可以bean的作用域,参数有 prototype.request.session.singleton. 1)singleton为单例,IoC容器只会创 ...

  9. iOS多语言设置

    最近公司做的项目需要向国外推广,因此app需要添加相应的语言设置,为此整理记录下多语言设置的过程.如有不对的地方,欢迎各位大神指正.下面就详细介绍下设置的过程: 1.基本设置 第一步:首先在 项目工程 ...

  10. Cannot set HTTP gem source: “source https://rubygems.org not present in cache”

    My ruby version in Windows 10: > ruby -v ruby 2.3.1p112 (2016-04-26 revision 54768) [i386-mingw32 ...