线程池虽然好用,但限制也不少:

(1)总觉得默认的 MaxThread 小了一点,每次使用都要手工调大= =

(2)任务不能等待完成

(3)任务一旦加入不能取消,甚至不知道是正在排队/正在执行/执行完毕

(4)最恶心的一点,全是 MTAThread,好多COM都不能用。ClipBoard、WebBrowser ...

实在不能忍了,自己写了个“任务池”,模拟线程池的功能。不同点有:

(1)没有数量上限,新进的任务不需要排队(但任务太多可能影响系统性能)

(2)任务的创建和开始可以分开,也可以创建时就开始。

(3)任务可等待

(4)任务可强制取消,虽然非常非常非常非常非常不建议这么做,这可能造成不可预知的问题

(5)可以选择任务线程的 ApartmentState (MTA / STA / Unknown = 无所谓)

相同点在于:

(1)保证(近乎绝对的)线程安全,逻辑上没有线程不安全的地方

(2)线程可重用

不足之处在于:

(1)还是应该添加限制线程数目的功能,避免对系统性能造成太大影响

(2)任务应该支持“尝试取消”操作

(3)有些 TTask 类里的字段应该对用户只读,但语法上实在做不到= =(没有 friend 关键字)

Version 1.0

 using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net.Mime;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading; // ReSharper Disable InconsistentNaming namespace Efficiency.Core { //+ delegate TTaskDelegate
public delegate void TTaskDelegate(TTask task, object param); //+ class TTask
public class TTask { public readonly AutoResetEvent Event = new AutoResetEvent(false);
public readonly ApartmentState ApartmentState; public readonly TTaskDelegate Callback;
public readonly object Param; public Thread Thread { get; set; } //-- .ctor()
public TTask(TTaskDelegate callback, object param, ApartmentState state)
{
this.ApartmentState = state;
this.Param = param;
this.Callback = callback;
} public int Status = ;
// 0: Working...
// 1: Marked Finished
// 2: Marked Force Exited
public bool IsFinished => (this.Status != ); public bool Wait(int timeout = -) => this.Event.WaitOne(timeout); //-- void ForceExit()
public void ForceExit()
{
if (Interlocked.CompareExchange(ref this.Status, , ) != ) return;
try {
this.Thread.Abort();
}
catch {
// Ignored
}
} //-- void ForceExit(out Exception)
public bool ForceExit(out Exception exception)
{
exception = null;
if (Interlocked.CompareExchange(ref this.Status, , ) != ) return true;
try {
this.Thread.Abort();
return true;
}
catch(Exception ex) {
exception = ex;
return false;
}
}
} // class TTask //+ class TTaskPool
public static class TTaskPool { //+ class TTaskPool.TTaskThreadContext
private class TTaskThreadContext {
public static volatile int CanExit = ; public readonly AutoResetEvent WaitEvent = new AutoResetEvent(false);
public readonly Queue<Thread> ThreadQueue;
public TTask Task; //-- .ctor()
public TTaskThreadContext(Queue<Thread> threadQueue, TTask task)
{
this.ThreadQueue = threadQueue;
this.Task = task;
} } // class TTaskPool.TTaskThreadContext private static readonly Queue<Thread> m_STAQueue = new Queue<Thread>();
private static readonly ReaderWriterLock m_STARWLock = new ReaderWriterLock();
private static readonly Dictionary<Thread, TTaskThreadContext> m_STAContext =
new Dictionary<Thread, TTaskThreadContext>(); private static readonly Queue<Thread> m_MTAQueue = new Queue<Thread>();
private static readonly ReaderWriterLock m_MTARWLock = new ReaderWriterLock();
private static readonly Dictionary<Thread, TTaskThreadContext> m_MTAContext =
new Dictionary<Thread, TTaskThreadContext>(); private static int s_PeakSTATaskCount = ;
public static int PeakSTATaskCount => s_PeakSTATaskCount; private static int s_PeakMTATaskCount = ;
public static int PeakMTATaskCount => s_PeakMTATaskCount; public static int PeakTaskCount => PeakMTATaskCount + PeakSTATaskCount; //-- TTask CreateTask(TTaskDelegate, object)
[MethodImpl(0x100)]
public static TTask CreateTask(
TTaskDelegate callback,
object param = null,
ApartmentState state = ApartmentState.Unknown)
{
if (callback == null) {
throw new ArgumentNullException(nameof(callback));
}
return new TTask(callback, param, state);
} //-- bool TryInsertTask(TTask, ThreadQueue<Thread>, Dictionary<Thread, TTaskThreadContext>, ReaderWriterLock)
[MethodImpl(0x100)]
private static bool TryInsertTask(
TTask task,
Queue<Thread> queue,
Dictionary<Thread, TTaskThreadContext> dict,
ReaderWriterLock rwlock,
ApartmentState state,
bool force)
{
Thread thread = null;
TTaskThreadContext context;
bool isNew;
lock (queue) {
if (queue.Count == ) {
if (! force) return false;
isNew = true;
}
else {
thread = queue.Dequeue();
isNew = false;
}
} if (isNew) {
thread = new Thread(TTaskThreadRoutine);
thread.SetApartmentState(state);
thread.IsBackground = true;
if (state == ApartmentState.STA)
Interlocked.Increment(ref s_PeakSTATaskCount);
else
Interlocked.Increment(ref s_PeakMTATaskCount); context = new TTaskThreadContext(queue, task);
rwlock.AcquireWriterLock(-);
dict.Add(thread, context);
rwlock.ReleaseWriterLock();
thread.Start(context);
}
else {
rwlock.AcquireReaderLock(-);
context = dict[thread];
rwlock.ReleaseReaderLock();
context.Task = task;
context.WaitEvent.Set();
} return true;
} //-- void InsertTask(TTask)
public static void InsertTask(TTask task)
{
if (task == null) {
throw new ArgumentNullException(nameof(task));
} switch (task.ApartmentState) {
case (ApartmentState.STA):
TryInsertTask(task, m_STAQueue, m_STAContext, m_STARWLock, ApartmentState.STA, true);
break; case (ApartmentState.MTA):
TryInsertTask(task, m_MTAQueue, m_MTAContext, m_MTARWLock, ApartmentState.MTA, true);
break; default:
if (TryInsertTask(task, m_MTAQueue, m_MTAContext, m_MTARWLock, ApartmentState.MTA, false)) return;
if (TryInsertTask(task, m_STAQueue, m_STAContext, m_STARWLock, ApartmentState.STA, false)) return;
TryInsertTask(task, m_MTAQueue, m_MTAContext, m_MTARWLock, ApartmentState.MTA, true);
break;
} } //-- TTask CreateInsertTask(STATaskDelegate, object, ApartmentState)
[MethodImpl(0x100)]
public static TTask CreateInsertTask(
TTaskDelegate callback,
object param = null,
ApartmentState state = ApartmentState.Unknown)
{
if (callback == null) {
throw new ArgumentNullException(nameof(callback));
}
TTask task = new TTask(callback, param, state);
InsertTask(task);
return task;
} //-- void TTaskThreadRoutine(object)
private static void TTaskThreadRoutine(object threadContext)
{
TTaskThreadContext context = (TTaskThreadContext)threadContext;
Thread thisThread = Thread.CurrentThread;
while (true) {
if (TTaskThreadContext.CanExit != ) return;
thisThread.Priority = ThreadPriority.Normal; TTask task = context.Task;
task.Callback.Invoke(task, task.Param);
task.Thread = thisThread;
thisThread.IsBackground = true; task.Event.Set();
if (Interlocked.CompareExchange(ref task.Status, , ) == ) {
try {
thisThread.Abort();
}
catch {
// Ignored
}
}
if (TTaskThreadContext.CanExit != ) return; lock (context.ThreadQueue) {
context.ThreadQueue.Enqueue(thisThread);
}
context.WaitEvent.WaitOne(-);
}
} } // class TTaskPool } // namespace Efficiency.Core

[.NET] 自己实现任务池(模仿线程池)的更多相关文章

  1. Python 线程池的原理和实现及subprocess模块

    最近由于项目需要一个与linux shell交互的多线程程序,需要用python实现,之前从没接触过python,这次匆匆忙忙的使用python,发现python确实语法非常简单,功能非常强大,因为自 ...

  2. 简单理解设计模式——享元模式-线程池-任务(tesk)

    前面在写到多线程的文章的时候,一直想写一篇关于线程池等一系列的文章,做一下记录,本篇博客记录一下设计模式中享元模式的设计思想,以及使用享元模式的实现案例——线程池,以及线程池的简化版——任务(tesk ...

  3. 模仿.Net ThreadPool的线程池控件

    http://www.2ccc.com/btdown.asp?articleid=5953 ftp://download:S3cirpYW3DoR@www.2ccc.com/vcl/system/20 ...

  4. Nginx 引入线程池,提升 9 倍性能

    转载:http://blog.csdn.net/wuliusir/article/details/50760357 众所周知,NGINX 采用异步.事件驱动的方式处理连接.意味着无需对每个请求创建专门 ...

  5. java中线程池的使用方法

    1 引入线程池的原因 由于线程的生命周期中包括创建.就绪.运行.阻塞.销毁阶段,当我们待处理的任务数目较小时,我们可以自己创建几个线程来处理相应的任务,但当有大量的任务时,由于创建.销毁线程需要很大的 ...

  6. Java 并发编程——Executor框架和线程池原理

    Eexecutor作为灵活且强大的异步执行框架,其支持多种不同类型的任务执行策略,提供了一种标准的方法将任务的提交过程和执行过程解耦开发,基于生产者-消费者模式,其提交任务的线程相当于生产者,执行任务 ...

  7. 探究ElasticSearch中的线程池实现

    探究ElasticSearch中的线程池实现 ElasticSearch里面各种操作都是基于线程池+回调实现的,所以这篇文章记录一下java.util.concurrent涉及线程池实现和Elasti ...

  8. j.u.c系列(01) ---初探ThreadPoolExecutor线程池

    写在前面 之前探索tomcat7启动的过程中,使用了线程池(ThreadPoolExecutor)的技术 public void createExecutor() { internalExecutor ...

  9. Java 并发编程——Executor框架和线程池原理

    Java 并发编程系列文章 Java 并发基础——线程安全性 Java 并发编程——Callable+Future+FutureTask java 并发编程——Thread 源码重新学习 java并发 ...

随机推荐

  1. vba单元格背景色

    cells(i,j).interior.color=5287936  green =255 red

  2. Shell中的空格和引号

    空格对于linux的shell是一种很典型的分隔符,所以给变量赋值的时候中间不能够有空格.而单引号和双引号,都是为了解决中间有空格的问题.比如string1=this is a string,这样执行 ...

  3. EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(八)

    前言 本篇幅将对系统的菜单管理模块进行说明,系统的菜单采用树形结构,这样可以更好地方便层级设计和查看.本示例将说明如何通过EntityFramework读取递归的菜单树形结构,以及结合EasyUI的t ...

  4. Java面试常见各种概念区别比较

    Hashtable 和 HashMap之间的区别 Hashtable是继承了Dictionary,是线程安全的.HashMap实现了Map接口,不是线程安全的.HashMap是Hashtable的轻量 ...

  5. 日常小测:颜色 && Hackerrank Unique_colors

    题目传送门:https://www.hackerrank.com/challenges/unique-colors 感谢hzq大神找来的这道题. 考虑点分治(毕竟是路经统计),对于每一个颜色,它的贡献 ...

  6. Java集合类学习笔记(Set集合)

    Set集合不允许包含相同的元素,如果试图把两个相同的元素加入同一个Set集合中,则添加操作失败,add()方法返回false,且新元素不会被加入. HashSet类的特点: 不能保证元素的排列顺序,顺 ...

  7. Fragment的onResume

    需求:Fragment每次由不可见到可见时的回调. 可能最先想到的是onResume方法,实际使用中Fragment的onResume调用时机与其Activity一致,因此类似与viewPager搭配 ...

  8. Matlab_Graphics(1)_2D

    1.Add title ,axis Lables, and Legend to Graph: x=linspace(-*pi,2pi,); y1=sin(x); y2=cos(x); figure p ...

  9. css 中content内容特殊形状

    用到的一些特殊字符和图标html代码<div class="cross"></div>css代码.cross{    width: 20px;    hei ...

  10. NSLOG打印不全的问题

    #ifdef DEBUG #define NSLog(FORMAT, ...) fprintf(stderr, "%s:%zd\t%s\n", [[[NSString string ...