C#基础系列:多线程的常见用法详解
作者:网络转载 发布时间:[ 2016/3/3 11:25:53 ] 推荐标签:.NET 测试开发技术 线程
(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();
});
}
}
需要注意:Semaphore对象的数量需要根据服务器的性能来设定;System.Threading.Tasks.Parallel.ForEach这种方式表示同时启动lstTestBed.Length个线程去做一件事情,可以理解为
foreach(var oTestbed in lstTestBed)
{
Thread oThread=new Thread(new ThreadStart({ ...}));
}
(4) 多线程里面还有一个值得一说的SpinWait类,用于提供对基于自旋的等待的支持。也是说支持重复执行一个委托,知道满足条件返回,我们来看它的用法:
public static void SpinUntil(Func<bool> condition);
public static bool SpinUntil(Func<bool> condition, int millisecondsTimeout);
public static bool SpinUntil(Func<bool> condition, TimeSpan timeout);
这个方法有三个构造函数,后两个需要传入一个时间,表示如果再规定的时间内还没有返回则自动跳出,防止死循环。
SpinWait.SpinUntil(() =>
{
bIsworking = m_oClient.isworking(new isworking()).result;
return bIsworking == false;
}, 600000);
//如果等了10分钟还在跳纤则跳出
if (bIsworking)
{
oRes.ErrCode = "false交换机跳纤时间超过10分钟,请检查异常再操作";
return oRes;
}
博主使用过的多线程用法大概这么三大类,当然这些其中还涉及很多细节性的东西,博主原来使用这些的时候经常出现各种莫名的问题,可能还是没用好的原因,对这些东西理解还不够深刻。如果大家也遇到类似的问题可以拿出来探讨!!
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系SPASVO小编(021-61079698-8054),我们将立即处理,马上删除。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11热门文章
常见的移动App Bug??崩溃的测试用例设计如何用Jmeter做压力测试QC使用说明APP压力测试入门教程移动app测试中的主要问题jenkins+testng+ant+webdriver持续集成测试使用JMeter进行HTTP负载测试Selenium 2.0 WebDriver 使用指南