- 浏览: 739633 次
- 性别:
- 来自: 北京
-
文章分类
- 全部博客 (1081)
- [网站分类]1.首页原创精华.NET区(包含架构设计、设计模式)(对首页文章的要求:原创、高质量、经过认真思考并精心写作) (0)
- [网站分类]2..NET新手区(用于发表不合适发表在首页的.NET技术文章,包括小经验、小技巧) (1)
- [网站分类]3.非技术区(技术之外的文章,但不要涉及任何政治内容) (0)
- [网站分类]4.其他技术区 (0)
- [网站分类]5.企业信息化 (0)
- [网站分类]6.读书心得区(技术书籍阅读心得、书籍推荐) (0)
- [网站分类]7.提问区(.NET技术方面的提问) (2)
- [网站分类]8.技术转载区(.NET技术文章转载, 请注明原文出处) (0)
- [网站分类]9.求职招聘区(个人求职、企业招聘) (0)
- [网站分类]Dottext区 (0)
- [网站分类]GIS技术 (0)
- [网站分类]IT英才专区(IT职场交流) (0)
- [网站分类]SharePoint (0)
- [网站分类]博客园.NET俱乐部(俱乐部组织与活动方面的文章) (0)
- [网站分类]软件发布区(发布自己开发的代码、软件) (0)
- [网站分类]网站管理区(网站管理方面的疑问、建议、意见, 寻求管理员帮助) (0)
- [网站分类]业界新闻 (1)
- 技术 (1)
- [随笔分类]生活感悟 (10)
- [随笔分类]C# (30)
- [随笔分类]AjaxPro教程 (3)
- [发布至博客园首页] (5)
- [随笔分类]简历 (0)
- [随笔分类]Linux (2)
- [随笔分类]技术聚会 (2)
- [随笔分类]ORM (1)
- [随笔分类]php (1)
- [随笔分类]创业 (1)
- [随笔分类]奇技淫巧 (1)
- [随笔分类]计划 (1)
- [随笔分类]架构&分层 (1)
- [随笔分类]整合行销 (1)
- [随笔分类]mac (1)
- [网站分类].NET新手区 (45)
- [网站分类]非技术区 (5)
- [网站分类]招聘区 (0)
- [随笔分类]单元测试 (1)
- [网站分类]其他技术区 (3)
- [网站分类]代码与软件发布 (6)
- [网站分类]提问区 (24)
- [随笔分类]ASP.NET (2)
- [随笔分类]FAQ (12)
- [随笔分类]开发人员工具 (1)
- [随笔分类]朗志轻量级项目管理解决方案 (1)
- [网站分类]读书区 (1)
最新评论
-
天使建站:
写和乱七八糟的 不知道从哪复制过来的 还是看这里吧j ...
jquery数组 -
hyn450:
你好,我最近也想了解一下竞争情报。不知道能不能交流一下呢 ?
最近的工作 -
lattimore:
这个连接打不开了阿!
使用vnc连ubuntu desktop -
MZhangShao:
奉劝你一句,以后在Ubuntu 用apt-get安装成功的软件 ...
关于xrdp的安装设置 -
f002489:
strftime
python下datetime类型的转换
在自制线程1中,我们实现了一个,用于低优先级,可设定最大执行线程,可在执行任务过程或是在队列中的任务时销毁的线程不耻,主要应用于需要花费时间较长的任务的工作。
任务执行的时间长了,说不定因为某些原因,线程执行的任务就死在那了,针对这点加入这样一个功能,记录这个任务执行开始的时间,当它执行的时间如果超过了1h,我们就认为这个工作超过我们的预期了,将它Abort掉。并掉用回调函数ErrCallback,通知客户进行后续的处理工作。如果正常执行可以有一个SuccCallback来处理完成后的操作,当然两个回调是非强制性的。另外执行的任务可以返回一个结果值,改变了build-in threadpool 的WaitCallback没有返回值的设计
在设计线程池的功能是我曾经考虑单独为每个任务设定超时执行的时间,可是这样的话似乎要为每个任务创建一个定时器来监控任务的执行时间上限是否到了(可能是我没有想到好的解决方案,高手支招哈),基于这种情况,大多数任务执行的时间都非常短,而且也不会出现特别的状况,实际当中,只有极个别的任务会因为一些特殊情况长期未完成任务,因此我考虑了使用一个线程来轮询,interval time设置的相关长一些,这样来清理异常任务占用的线程。而且这样实现起来也相对简单一些。下面给出基于自制线程1篇后的改进版线程池。


<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Rhino.Commons;
namespace ThreadPool
{
public delegate object WaitCallback2(object state);
public delegate void SuccCallback(object state,object result);
public delegate void ErrCallback(object state);
/// <summary>
/// 此线程池的作用是将某一类特殊的任务交给此线程池执行,
/// 可以设定该线程池的最大线程数,
/// 这类线程池的优点时,占用的资源少,优先级低,
/// 适合于执行任务需要长期执行,不考虑时间因素的任务
/// 同时根据在传入线程池时的标记key,可以Aborted指定任务,
/// 若该任务正在执行或尚在执行队列中
/// </summary>
public static class MyThreadPool
{
static object obj = new object();
static AutoResetEvent wait = new AutoResetEvent(false);
static AutoResetEvent wait2 = new AutoResetEvent(false);
static MyThreadPool()
{
System.Threading.ThreadPool.RegisterWaitForSingleObject(wait, new WaitOrTimerCallback(aa), state, 2000,true);
SetMaxThreadNum(1);
SetMaxExecTime(true, 10000);
}
/// <summary>
/// 设定单线程允许执行任务的最长时间,该方法不能在运行时改变,须事前设定
/// </summary>
/// <param name="b"></param>
/// <param name="time"></param>
private static void SetMaxExecTime(bool b, int time)
{
IsLimitedExecTime = b;
MaxLimitedTime = time;
if (IsLimitedExecTime)
System.Threading.ThreadPool.RegisterWaitForSingleObject(wait2, new WaitOrTimerCallback(bb), state,
MaxLimitedTime, true);
}
private static void bb(object state, bool timedOut)
{
lock(obj)
{
Dictionary<string,WorkerThread> temp=new Dictionary<string, WorkerThread>();
foreach(var kvp in dict)
{
if(DateTime.Now.Subtract(kvp.Value.StartExecTime).TotalMilliseconds>MaxLimitedTime)
{
temp.Add(kvp.Key,kvp.Value);
}
}
foreach(var kvp in temp)
{
Aborted(kvp.Key);
}
System.Threading.ThreadPool.RegisterWaitForSingleObject(wait2, new WaitOrTimerCallback(bb), state, MaxLimitedTime, false);
}
}
public static int MaxLimitedTime { get; set; }
public static bool IsLimitedExecTime { get; set; }
private static void aa(object state, bool timedOut)
{
lock (obj)
{
//判断任务队列中有无积压的任务且有无空闲的线程,如果符合上述条件则执行之
List<string> removeKey = new List<string>();
List<WorkerThread> newTask=new List<WorkerThread>();
//Dictionary<string,WorkerThread> addDict=new Dictionary<string, WorkerThread>();
foreach (var kvp in dict)
{//kvp.Value.ThreadState == ThreadState.Unstarted ||
if (kvp.Value.Thread.ThreadState == ThreadState.Suspended)
{
//dict.Remove(kvp.Key);//cancle because of lock
WorkerThread a=queue.FirstOrDefault();
if (a != null)
{
removeKey.Add(kvp.Key);
//addDict.Add(a.Key, kvp.Value.Change(a));
newTask.Add(kvp.Value.Change(a));
queue.RemoveAt(0);
//dict.Add(a.Key, kvp.Value.Change(a));//cancle because of lock
//将参数加到线程中,并改变线程的状态
//dict[a.Key].Thread.Resume();
}
else
break;
//else
//{
// System.Threading.ThreadPool.RegisterWaitForSingleObject(wait, new WaitOrTimerCallback(aa), state,
// 2000, true);
// return;
//}
}
}
removeKey.ForEach(t=>dict.Remove(t));
newTask.ForEach(t =>
{
t.StartExecTime = DateTime.Now;
dict.Add(t.Key, t);
t.Thread.Resume();
});
while (queue.Count > 0 && dict.Count < MaxThreadNum)
{
//未到线程池最大池程数时,增加线程
WorkerThread b = queue.FirstOrDefault();
if (b!=null)
{
queue.RemoveAt(0);
//Thread thd = new Thread(new ThreadStart(b.Exec));
//thd.Priority = ThreadPriority.Lowest;
//dict.Add(b.Key, thd);
//thd.Start();
WorkerThread wt = new WorkerThread();
wt.Start(b);
dict.Add(wt.Key, wt);
wt.Thread.Start();
//将参数加到线程中,并改变线程的状态
}
}
System.Threading.ThreadPool.RegisterWaitForSingleObject(wait, new WaitOrTimerCallback(aa), state, 2000,
true);
}
}
//private static int _maxThreadNum = 1;
public static int MaxThreadNum
{
//get { return _maxThreadNum; }
//set { _maxThreadNum = value; }
get; set;
}
public static void SetMaxThreadNum(int num)
{
if (num < 1)
num = 1;
MaxThreadNum = num;
}
/// <summary>
/// 任务执行队列
/// </summary>
//static ThreadSafeQueue<WorkerThread> queue = new ThreadSafeQueue<WorkerThread>();
static List<WorkerThread> queue=new List<WorkerThread>();
/// <summary>
/// 目前暂定为只使用一个线程,以免耗近资源
/// </summary>
static Dictionary<string, WorkerThread> dict = new Dictionary<string, WorkerThread>(1);
private static object state;
private static WorkerThread FindSpecificWorkerThreadByKey(string key)
{
WorkerThread wt;
dict.TryGetValue(key, out wt);
return wt;
}
public static void Aborted(string key)
{
//lock (obj)
//{
#region old way now extract method FindSpecificWorkerThreadByKey to split this
//WorkerThread v;
//if (dict.TryGetValue(key, out v))
//{
// v.Thread.Abort();
// //在调用Abort方法时,在指定线程上引发ThreadAbortException。以开始终止此线程的
// //过程。ThreadAbortException是—个可以由应用程序代码捕获的特殊异常,但除非调用
// //ResetAbort,否则会在catch块的结尾再次引发它。ResetAbod可以取消Abort的请求,并
// //阻止ThreadAbortException终止此线程。但是,线程不一定会立即中止,或者根本不中止。
// //如果线程在作为中止过程的一部分被调用的finally块中做非常大量的计算,从而无限期延
// //迟中止操作,则会发生这种情况。若要确保线程已经终止,请在调用Abort之后对线程调
// //用Join方法。
// v.Thread.Join();
// dict.Remove(key);
//}
#endregion
WorkerThread v = FindSpecificWorkerThreadByKey(key);
//没有发现指定key的线程表示,对应该key的任务已经执行完了,不需要再来取消该任务
//或者指的key的线程虽然还在但它的状态已变为suspended,任务已完成,将等待下一个任务,实际不需要终止该线程
//只有但指定的key的任务在执行时才删除
if (v != null && v.Thread.ThreadState!=ThreadState.Suspended)
{
dict.Remove(key);
/*
在调用Abort方法时,在指定线程上引发ThreadAbortException。以开始终止此线程的
过程。ThreadAbortException是—个可以由应用程序代码捕获的特殊异常,但除非调用
ResetAbort,否则会在catch块的结尾再次引发它。ResetAbod可以取消Abort的请求,并
阻止ThreadAbortException终止此线程。但是,线程不一定会立即中止,或者根本不中止。
如果线程在作为中止过程的一部分被调用的finally块中做非常大量的计算,从而无限期延
迟中止操作,则会发生这种情况。若要确保线程已经终止,请在调用Abort之后对线程调
用Join方法。
*/
v.Thread.Abort();
v.Thread.Join();
if (v.ErrorCallback != null)
v.ErrorCallback(v.State);
}
//任务如果还在队列中则删除该任务
int index = queue.FindIndex(t => t.Key == key);
if (index>-1)
queue.RemoveAt(index);
wait.Set();
//}
}
public static void QueueUserWorkItem(WaitCallback2 callback, object state,string key,SuccCallback succ,ErrCallback err)
{
WorkerThread p = new WorkerThread()
{
WaitCallback = callback,
State = state,
Key = key,
ErrorCallback=err,
SuccessCallback=succ
};
//queue.Enqueue(p);
queue.Add(p);
wait.Set();
}
public static void QueueUserWorkItem(WaitCallback2 callback, object state,SuccCallback succ,ErrCallback err)
{
QueueUserWorkItem(callback, state, System.Guid.NewGuid().ToString(),succ,err);
}
public static void QueueUserWorkItem(WaitCallback2 callback, object state, string key)
{
//WorkerThread p = new WorkerThread()
// {
// WaitCallback = callback,
// State = state,
// Key = key
// };
////queue.Enqueue(p);
//queue.Add(p);
//wait.Set();
QueueUserWorkItem(callback, state, key, null, null);
}
public static void QueueUserWorkItem(WaitCallback2 callback,object state)
{
QueueUserWorkItem(callback, state, System.Guid.NewGuid().ToString());
}
}
public class WorkerThread
{
public DateTime StartExecTime { get; set; }
public Thread Thread { get; set; }
public string Key { get; set; }
public WaitCallback2 WaitCallback { get; set; }
public SuccCallback SuccessCallback { get; set; }
public ErrCallback ErrorCallback { get; set; }
public Object State { get; set; }
public void Exec()
{
while (true)
{
if (this.SuccessCallback != null)
this.SuccessCallback(this.State,this.WaitCallback(this.State));
else
this.WaitCallback(this.State);
this.Thread.Suspend();
}
}
public WorkerThread Change(WorkerThread wt)
{
this.Key = wt.Key;
this.WaitCallback = wt.WaitCallback;
this.State = wt.State;
this.StartExecTime = wt.StartExecTime;
this.ErrorCallback = wt.ErrorCallback;
this.SuccessCallback = wt.SuccessCallback;
return this;
}
public void Start(WorkerThread wt)
{
this.Change(wt);
this.Thread = new Thread(new ThreadStart(this.Exec));
this.Thread.Priority = ThreadPriority.Lowest;
}
//public void Start(WaitCallback callback,Object state)
//{
// this.WaitCallback = callback;
// this.State = state;
// if(this.Thread==null){
// this.Thread = new Thread(new ThreadStart(this.Exec));
// this.Thread.Priority = ThreadPriority.Lowest;
// this.Thread.IsBackground = true;
// this.Thread.Start();
// return;
// }
// if(this.Thread.ThreadState==ThreadState.Suspended)
// {
// this.Thread.Resume();
// }
//}
}
}
下面是测试用例


<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using ThreadPool;
namespace ThreadPoolTest
{
class Class6
{
static void Main(string[] args)
{
object state1="beijing";
object state2 = "zhejiang";
MyThreadPool.QueueUserWorkItem(new WaitCallback2(ExecMethod1),state1,new SuccCallback(SuccMethod),new ErrCallback(ErrMethod));
MyThreadPool.QueueUserWorkItem(new WaitCallback2(ExecMethod2), state2, new SuccCallback(SuccMethod), new ErrCallback(ErrMethod));
Console.ReadLine();
}
private static object ExecMethod2(object state)
{
while(true)
{
Thread.Sleep(1500);
Console.WriteLine("welcome to" + state);
}
return null;
}
private static void ErrMethod(object state)
{
Console.WriteLine("ErrMethod

Console.WriteLine("transform params:{0}",state);
}
private static void SuccMethod(object state,object result)
{
Console.WriteLine("SuccMethod

Console.WriteLine("hey erick,you are now in {0},{1}",state,result);
}
private static object ExecMethod1(object state)
{
Console.WriteLine("ExecMethod1

return "welcome to" + state;
}
}
}
目前这个线程池还有这么三个问题,
1.初始时是没有线程的,当加入任务时根据需要会逐步增加到最大线程,可是之后即使线程空闲,也不会将闲置的线程不abort掉,目前还没想到该怎么解决请高手支招啊,
2.代码还待严重重构,目前先解决功能性的问题先。
3.测试不够严谨
请听我下回分解
PS:大家只想用一般性的线程池功能的话,推荐使用smartthreadpool
发表评论
-
关于分层架构中的业务实体层的使用一直不太清楚,可否指点一下?
2007-03-23 09:10 681我知道业务逻辑层又可细分为三个层次,分别是业务外观层业务规则层 ... -
xml反串行化
2007-07-02 17:23 7441using System; 2using Syste ... -
WriteXmlSchema(xsdFileName)和GetXmlSchema()输出的内容的差异
2007-07-04 19:00 907利用DataSet.ReadXml载入一个xml文件,再使用G ... -
对websharp中aspect的改进(待续)
2007-11-17 14:27 723缘起 为了在我的《朗志轻量级项目管理解决方案》项目中应用 ... -
WebSharp Aspect改进(续2)
2007-11-19 21:39 705接着上次在《朗志轻量级项目管理解决方案》中对Aspec ... -
TreeView(树形控件)中常用到的属性和事件
2007-11-19 22:22 13031.TreeView(树形控件) ... -
有没有适合的的面向对象的查询语言(Object Query Language)
2007-11-28 10:15 771在我做《朗志轻量级项目管理解决方案》的过程中,我希望 ... -
问题解答集
2007-11-29 18:11 4501 如何在源代码的目录下添加一个测试文件 ... -
FckEditor自定义按钮
2007-11-29 18:35 843目录 FckEditor自定义按钮 1 目录 ... -
GhstDoc2.1.1使用手册
2007-11-29 18:39 737目录 GhstDoc2.1.1使用手册 1 ... -
Log4net使用说明
2007-11-29 18:44 799Log4net使用说明 1 修改历史纪录 ... -
MySQLHelper类使用说明
2007-11-29 18:46 1336目录 MySQLHelper类使用说明 1 目录 ... -
NDoc1.3.1使用手册
2007-11-29 18:47 781目录 NDoc1.3.1使用手册 1 目录 ... -
程序中操作Word
2007-11-29 18:52 740目录 程序中操作Word 1 目录 2 ... -
利用SMTP服务发送电子邮件
2007-11-29 18:58 1360目录 利用SMTP服务发送电子邮件 1 目录 ... -
程序中操作Excel
2007-11-29 18:59 654目录 程序中操作Excel 1 目录 ... -
访问被拒绝:“AjaxPro”的解决方案
2007-11-29 19:01 578目录 访问被拒绝:&qu ... -
sqlserver的版本号
2008-02-27 21:01 829当你安装了sqlserver 2005之后你就可以使用sqls ... -
在安装有VS2008beta2版本的机子上使用vs2005进行部署出现问题的解决方法
2008-02-27 21:13 691我知道,2008rtm发布已经很久了,不巧的是同学在我的机子上 ... -
忙话codesmith
2008-07-28 15:01 875为什么不是闲话,因为我很忙,项目中新问题是接连不断,上一篇讲到 ...
相关推荐
本项目标题为“Asynchronous-Server”,它使用了非阻塞I/O(Non-blocking I/O)和自制线程池来实现这种异步服务器模型。以下是关于这个主题的详细知识: 1. **非阻塞I/O**:非阻塞I/O是与传统的阻塞I/O相反的一种...
在“易语言自制系统运行时间计时器源码.7z”这个压缩包中,我们可以推测包含的是一个使用易语言编写的程序,该程序的功能是计算并显示系统运行的时间,也就是自计算机启动以来的持续时间。 计时器是编程中的一个...
虽然VB标准库提供了内建的Replace函数来执行这个任务,但有时开发者可能需要自定义更复杂的替换逻辑,这时自制替换函数就显得尤为重要。下面我们将详细探讨如何在VB中创建自定义替换函数以及其相关知识点。 1. **VB...
### 自制MFC函数大全:绘图功能详解 在深入探讨MFC(Microsoft Foundation Classes)绘图函数之前,我们先简要了解MFC本身。MFC是微软提供的一套C++类库,用于简化Windows应用程序的开发过程。它封装了Windows API...
- lpfnTimerProc:定时器回调函数的地址,当定时器到期时,该函数会被调用。 2. **Declare语句**: - 在VB中,我们需要使用Declare语句来声明并导入API函数。例如: ```vb Private Declare Function SetTimer ...
【自制ULink2图纸解析】 ULink2是德州仪器(TI)公司推出的一款USB到JTAG适配器,常用于嵌入式系统开发中的调试和编程。它通过USB接口连接到计算机,然后通过JTAG接口与目标设备进行通信,帮助开发者进行程序下载、...
这个“ICD2自制(串口)”项目似乎涉及到用户自行制作或修改ICD2硬件,使其能够通过串行接口进行通信,从而实现对微控制器的编程和调试。 首先,ICD2的工作原理是利用单片机的串行通信接口(如UART)与主机(如个人...
“PIC ICD2自制资料”这一标题表明了这是一份关于PIC微控制器的编程接口卡(ICD2)的自制品。ICD2是Microchip Technology公司为编程和调试其系列微控制器设计的一种设备,尤其是PIC16F877和PIC16F877A型号。这里的...
标题中的“51核心自制鼠标PS2协议PAN3401光学芯片”是指使用51系列单片机设计的一款自制鼠标,它基于PS/2(Personal System/2)接口协议,并采用了PAN3401作为光学传感器。在本文中,我们将深入探讨这些关键知识点。...
【自制函数查询工具】是一款专为开发者设计的实用软件,旨在帮助用户快速查询和记忆日常开发中常用的函数。这款工具特别适用于使用VC++(Visual C++)编程环境的程序员,因为"VC"标签明确指出了它的适用范围。通过...
Powerbuilder,PB自制大数据导出,超6w限制,Powerbuilder,PB自制大数据导出,超6w限制,Powerbuilder,PB自制大数据导出,超6w限制,Powerbuilder,PB自制大数据导出,超6w限制,Powerbuilder,PB自制大数据导出,...
这通常涉及到事件监听和回调函数,当特定事件发生时,回调函数会被执行,比如播放声音或者显示通知。 此外,数据存储也是要考虑的问题。如果用户希望保存多个闹钟设置,那么就需要一种方式来持久化这些数据。这可能...
在PS3的生态系统中,自制系统(Custom Firmware,简称CFW)是一种非官方的固件,它允许用户绕过索尼的限制,执行未授权的软件,如备份游戏、运行Homebrew应用以及访问被封锁的区域内容。"4.86"代表的是这个自制系统...
这款插件通常会有一个120分钟的时间限制,意味着超过这个时长的视频可能无法完整下载。然而,"VideoDownloadHelper去除120分钟时间限制-高级版" 提供了解决这个问题的解决方案。 首先,我们要理解这个高级版的含义...
### 自制无源调幅收音机:详细解析与制作指南 #### 一、引言 随着无线电技术的不断进步,传统的矿石收音机似乎已经退出了历史舞台。然而,对于那些对无线电有着浓厚兴趣的爱好者们而言,无源收音机依然具有不可替代...
易语言提供了日期时间相关的函数,如“取系统时间”可以获取当前的日期和时间,而“取时间差”可以计算两个时间点之间的差值。 4. **界面显示**:计时器的运行结果需要在用户界面上展示,这可能涉及到“标签”或...
在这个"java自制struts2小框架"项目中,我们可以深入理解Struts2的核心概念和工作流程。 1. **MVC设计模式**:MVC模式是软件工程中的一种设计模式,用于分离业务逻辑(Model)、用户界面(View)和数据呈现...
【PS2自制引导卡傻瓜包】是一款专为PlayStation 2(PS2)游戏机设计的引导工具,它使得用户无需专业知识即可轻松制作引导卡。这个工具包简化了复杂的过程,让玩家能够将自制软件加载到PS2系统中,从而实现更多的功能...
《CPU自制入门》是一本专为对CPU设计与编程感兴趣的读者准备的经典书籍,它深入浅出地介绍了CPU的内部构造和工作原理,是CPU自制入门的绝佳指导资料。通过阅读这本书,你可以了解到从基础的逻辑门电路到复杂的微处理...
在Windows操作系统中,CPU时间片(也称为时间量子或时间槽)是系统分配给每个进程执行的时间单位。这个参数对系统的性能和响应性有直接影响。默认情况下,Windows会自动调整时间片长度以优化系统性能,但某些特殊...