Semaphore:其实.NET中的信号量(Semaphore)是操作系统维持的一个整数。当整数位0时。其他线程无法进入。当整数大于0时,线程可以进入。每当一个线程进入,整数-1,线程退出后整数+1。整数不能超过信号量的最大请求数。信号量在初始化的时候可以指定这个整数的初始值。
WaitHandle:这个类的,需要为每个线程创建一个WaitHandle对象并把它们放在一个数组中,然后用WaitHandle类中的WaitAll方法来等待这些 WaitHandle被调用Set方法。主意:当waihandle在线程池中的,数组的元素个数超过(>)64时,就会报异常(System.NotSupportedException: WaitHandle 的数目必须少于或等于 64 个)
看一个waitHandle的例子
class other
{
static void Main(string[] args)
{
Random randomGenerator = new Random();
AutoResetEvent[] resets=new AutoResetEvent[5];
for (int i = 0; i < 5; i++)
{
resets[i] = new AutoResetEvent(false);
int wTime = randomGenerator.Next(10)+1;
worker w = new worker(wTime, resets[i]);
Thread thrd1 = new Thread(new ThreadStart(w.work));
thrd1.Start();
}
WaitHandle.WaitAll(resets);//等待所有AutoResetEvent线程全部完成,再继续
Console.WriteLine("ALL worker done - main exiting.");
}
}
public class worker
{
public string name;
public int wTime;
public AutoResetEvent mEvent;
public worker(int w, AutoResetEvent m)
{
name = w.ToString();
wTime = w * 1000;
mEvent = m;
}
public void work()
{
Console.WriteLine(name + " worker thread waiting for " + wTime + "....");
Thread.Sleep(wTime);
Console.WriteLine(name + " worker thread back...");
mEvent.Set();//释放信号
}
}
项目中的例子
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
using Citi.Equity.QSDBScheduler.Common;
using System.Threading;
using System.IO;
using System.Data;
using EQTG.Database;
namespace Citi.Equity.ClientReport.VOLDBDaily
{
internal class VolCacheCalculator
{
private string asOfDate = string.Empty;
private static object syncObj = new object();
private IDbConnection connOutter = null;
private static string sqlTemplate = "select o.id,o.usym,o.pc,o.strike,o.expire,o.type,p.date,p.bidimp,p.askimp from VOLDB_VOL_OPTIONS o inner join VOLDB_VOL_PRICES p on o.id=p.id where o.usym = '{0}' and o.type = 2 and p.date={1};";
internal VolCacheCalculator(string asOfDate, IDbConnection conn)
{
this.asOfDate = asOfDate;
this.connOutter = conn;
DBUtil.setQueryTimeout(3600);
}
internal List<VolResult> Calculate()
{
List<VolResult> result = new List<VolResult>();
List<UndEntity> tckList = null;
try
{
tckList = GetTickerList(connOutter);
}
catch (Exception ex)
{
ourLogger.Error("Failed to get tck list", ex);
}
if (tckList == null || tckList.Count == 0)
return result;
if (File.Exists("Complete.txt"))
{
lock (syncObj)
{
File.Delete("Complete.txt");
}
}
SuperWaitHandle swh = new SuperWaitHandle();
System.Threading.Semaphore resource = new System.Threading.Semaphore(20, 20);//设置初始信号量为20
foreach (UndEntity tck in tckList)
{
StateWrap wrap = new StateWrap();
wrap.TCK = tck;
wrap.WaitEvent = swh.CreateWaitEvent();//增加一个AutoResetEvent到list中
ThreadPool.QueueUserWorkItem(delegate(object state)
{
IDbConnection conn = null;
StateWrap dataPack = (StateWrap)state;
string symbol = dataPack.TCK.Symbol;
int eod = dataPack.TCK.Eod;
double spot = dataPack.TCK.Spot;
try
{
resource.WaitOne();//占有一个信号量,如果这里是manualEventRestwaitone便会等待,Semaphore初始值是20,如果第21个就会等待
conn = MyDBUtil.CreateConnection(connOutter.ConnectionString);
string sql = string.Format(sqlTemplate, symbol, eod);
// force to execute GC
GC.Collect();
GC.WaitForPendingFinalizers();
DataSet ds = DBUtil.ExecuteDBQuery(sql, conn);
DataTable dtSource = ds.Tables[0];
List<VolResult> volCacheResult = BuildVolSurface(symbol, eod, spot, dtSource);
if (volCacheResult != null)
{
lock (syncObj)
{
result.AddRange(volCacheResult);
}
}
}
catch (Exception ex)
{
ourLogger.Error("Failed when build vol for " + symbol, ex);
}
finally
{
lock (syncObj)
{
using (StreamWriter sw = new StreamWriter(@"Complete.txt", true))
{
sw.WriteLine(symbol);
}
}
if (conn != null && conn.State != ConnectionState.Closed)
{
conn.Close();
conn = null;
}
resource.Release();//释放一个信号量(针对的是Semaphore)
dataPack.WaitEvent.Set();//释放Set命令(针对 waitHandle)
}
}, wrap);
}
swh.WaitAll();//等待所有线程全部计算完毕,再回到Main函数
return result;
}
private List<UndEntity> GetTickerList(IDbConnection conn)
{
List<UndEntity> list = new List<UndEntity>();
return list;
}
internal class UndEntity
{
public string Symbol { get; set; }
public int Eod { get; set; }
public double Spot { get; set; }
}
internal class VolResult
{
public string Symbol { get; set; }
public int Eod { get; set; }
public double Moneyness { get; set; }
public string Term { get; set; }
public double AvgImp { get; set; }
public double BA_spread { get; set; }
public double pc_spread { get; set; }
}
internal class StateWrap
{
public UndEntity TCK;
public AutoResetEvent WaitEvent;
}
internal class SuperWaitHandle
{
List<AutoResetEvent> list = new List<AutoResetEvent>();
public AutoResetEvent CreateWaitEvent()
{
AutoResetEvent autoEvent = null;
lock (this)
{
do
{
autoEvent = new AutoResetEvent(false);
}
while (autoEvent == null || list.Contains(autoEvent));
list.Add(autoEvent);
}
return autoEvent;
}
public void Reset()
{
list = new List<AutoResetEvent>();
}
public bool WaitAll()
{
List<AutoResetEvent> temp = new List<AutoResetEvent>(64);
for (int i = 0; i < list.Count; i++)
{
if (temp.Count == 64)
temp = new List<AutoResetEvent>(64);
if (temp.Count < 64)
{
temp.Add(list[i]);
if (temp.Count == 64 || temp.Contains(list.LastOrDefault()))
{
WaitHandle.WaitAll(temp.ToArray());//开64个AutoResetEvent的线程组,waitall阻止线程,直到所有线程都收到信号
}
}
}
return true;
}
}
internal class MyDBUtil
{
public static IDbConnection CreateConnection(string connectionString)
{
IDbConnection myDbCnn = null;
if (myDbCnn == null && connectionString != null)
{
myDbCnn = DBSelector.Factory.Connection(connectionString);
}
if (myDbCnn.State == ConnectionState.Closed)
{
myDbCnn = DBSelector.Factory.Connection(connectionString);
}
if (myDbCnn.State == ConnectionState.Closed)
{
myDbCnn.Open();
}
return myDbCnn;
}
}
}
}
http://www.cnblogs.com/LoveJenny/tag/%E6%B7%B1%E5%85%A5%E6%B5%85%E5%87%BA/
http://www.cnblogs.com/nokiaguy/category/144877.html
http://kb.cnblogs.com/page/42528/
http://blog.csdn.net/yl2isoft/article/details/11879625