因为异步操作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完全不用,最起码可以减少 共享变量的数量),减少了死锁的可能。当然异步操作也并非完美无暇。编写异步操作的复杂程度较高,程序主要使用回调方式进行处理,与普通人的思维方式有些出入,而且难以调试。
3、线程池的用法:
一般由于考虑到服务器的性能等问题,保证一个时间段内系统线程数量在一定的范围,需要使用线程池的概念。大概用法如下:
public class CSpiderCtrl
{
//将线程池对象作为一个全局变量
static Semaphore semaphore;
public static void Run()
{
//1. 创建 SuperLCBB客户端对象
var oClient = new ServiceReference_SuperLCBB.SOAServiceClient();
//2.初始化的时候new最大的线程池个数255(这个数值根据实际情况来判断,如果服务器上面的东西很少,则可以设置大点)
semaphore = new Semaphore(250, 255);
CLogService.Instance.Debug("又一轮定时采集...");
_TestBedGo(oClient);
}
//执行多线程的方法
private static void _TestBedGo(ServiceReference_SuperLCBB.SOAServiceClient oClient)
{
List<string> lstExceptPDUs = new List<string>(){
"SUPERLABEXP"
};
var oTestBedRes = oClient.GetTestBedExceptSomePDU(lstExceptPDUs.ToArray(), true);
if (CKVRes.ERRCODE_SUCCESS != oTestBedRes.ErrCode)
{
CLogService.Instance.Error("xxx");
return;
}
var lstTestBed = oTestBedRes.ToDocumentsEx();
System.Threading.Tasks.Parallel.ForEach(lstTestBed, (oTestBed) =>
{
//一次最多255个线程,超过255的必须等待线程池释放一个线程出来才行
semaphore.WaitOne();
//CLogService.Instance.Info("开始采集测试床:" + oTestBed[TBLTestBed.PROP_NAME]);
//Thread.Sleep(2000);
var strTestBedName = oTestBed[TBLTestBed.PROP_NAME] as string;
var strSuperDevIP = oTestBed[TBLTestBed.PROP_SUPERDEVIP] as string;
var strTestBedGID = oTestBed[TBLTestBed.PROP_GID] as string;
var strPdu = oTestBed[TBLTestBed.PROP_PDUGID] as string;
Thread.Sleep(new Random().Next(1000, 5000));
var oGetRootDevicesByTestBedGIDRes = oClient.GetRootDevicesByTestBedGID(strTestBedGID);
CLogService.Instance.Debug(strPdu + "——测试床Name:" + strTestBedName + "开始");
Stopwatch sp = new Stopwatch();
sp.Start();
if (oGetRootDevicesByTestBedGIDRes.ErrCode != CKVRes.ERRCODE_SUCCESS || oGetRootDevicesByTestBedGIDRes.Documents.Count < 2)
{
CLogService.Instance.Debug("shit -- 3实验室中测试床Name:" + strTestBedName + "2完成异常0");
//这里很重要的一点,每一次return 前一定要记得释放线程,否则这个一直会占用资源
semaphore.Release();
return;
}
var strXML = oGetRootDevicesByTestBedGIDRes.Documents[0];
var strExeName = oGetRootDevicesByTestBedGIDRes.Documents[1];
//var strExeName = "RateSpider";
var oSuperDevClient = new SuperDevClient(CSuperDev.ENDPOINT, string.Format(CSuperDev.SuperDevURL, strSuperDevIP));
try
{
oSuperDevClient.IsOK();
}
catch (Exception)
{
CLogService.Instance.Error("测试床Name:" + strTestBedName + "异常,插件没起");
semaphore.Release();
return;
}
//2.3.1.请求SuperDev.Server(SuperDevIP),发送Run(XML和Exename)
var oRunExeRes = new CKVRes();
try
{
oRunExeRes = oSuperDevClient.RunExeEx(strExeName, false, new string[] { strXML });
}
catch
{
//CLogService.Instance.Debug("测试床Name:" + strTestBedName + "异常:" + ex.Message);
}
sp.Stop();
CLogService.Instance.Debug(strPdu + "——测试床Name:" + strTestBedName + "完成时间" + sp.Elapsed);
//每一个线程完毕后记得释放资源
semaphore.Release();
});
}
}










