循环请求接口A获得A的数据后线程池添加A入库,同时线程池添加B和C,(将A作为条件提供给接口B和C发起请求),获得返回信息入库,
我用了,ManualResetEvent和AutoResetEvent,当A执行时候使B和C等待WaitOne(),B和C中都是循环请求的,B和C循环执行后设置信号,B设置 autoEvents[0].Set();C设置 autoEvents[1].Set();
问题是B完全可以执行完成然后执行了autoEvents[0].Set(),而C却没有全部执行完,有时候获取几十条就不动了, 有时候执行上千条也不动,但是根本没执行到autoEvents[1].Set();
不报异常,什么错误都没显示,就是不动了。我看不到线程是否还在运行中(不知道怎么看)。只用VS2010看到调试状态这些线程都是正常、
现在不知道怎么排查原因,为什么B可以正常执行,C却不能、代码有很多,做了精简
1 partial class CtripHotelBaseInfoService : ServiceBase 2 { 3 private readonly Timer _timer; 4 //Log.Info("循环下载数据开始--"); 5 private static readonly ILog Log = LogManager.GetLogger("CtripHotelBaseInfoLog"); 6 public CtripHotelBaseInfoService() 7 { 8 InitializeComponent(); 9 _timer = new Timer(Settings.Default.TimeSplit * 20 * 1000); //单位为分钟 10 _timer.Enabled = true; 11 _timer.Elapsed += SubmitTimerElapsed; 12 } 13 14 protected override void OnStart(string[] args) 15 { 16 // TODO: 在此处添加代码以启动服务。 17 _timer.Start(); 18 Log.Info("基本信息落地服务已启动...."); 19 } 20 21 protected override void OnStop() 22 { 23 // TODO: 在此处添加代码以执行停止服务所需的关闭操作。 24 _timer.Stop(); 25 Log.Info("基本信息落地服务已停止...."); 26 } 27 28 internal void SubmitTimerElapsed(object sender, ElapsedEventArgs e) 29 { 30 _timer.Stop(); 31 try 32 { 33 var serviceClient = new CtripHotelClient("CtripHotelService"); 34 CtripHotelDataContext context = new CtripHotelDataContext(Settings.Default.CtripHotelConnectionString); 35 var cityList = from c in context.Ctrip_Base_City select c; 36 int count = cityList.Count(); 37 Log.InfoFormat("共获取城市信息成功共{0}个", count); 38 foreach (var city in cityList) 39 { 40 Log.InfoFormat("请求接口,城市ID:{0},城市名称:{1} 的信息开始--", city.CityID, city.CityName); 41 42 string result = serviceClient.OTA_HotelSearchStr(city.CityID.ToString()); 43 44 if (string.IsNullOrEmpty(result)) 45 { 46 return; 47 } 48 Alpha alpha = new Alpha(); 49 OTA_HotelSearchRSEntity entity = new OTA_HotelSearchRSEntity(); 50 entity.head = new HeadEntity(); 51 #region 解析XML 52 53 #endregion 54 if (entity != null && entity.head != null && entity.OTA_Hotel != null 55 && entity.head.ResultCode.Equals("Success") && entity.head.SubCode.Equals("Success") 56 && entity.OTA_Hotel.Count > 0) 57 { 58 //添加到线程池中区 59 60 ThreadPool.QueueUserWorkItem(new WaitCallback(alpha.GetGotelBase), entity); 61 ThreadPool.QueueUserWorkItem(new WaitCallback(alpha.OTA_HotelDescriptiveInfo), entity.OTA_Hotel); 62 ThreadPool.QueueUserWorkItem(new WaitCallback(alpha.OTA_HotelRatePlan), entity.OTA_Hotel); 63 64 WaitHandle.WaitAll(alpha.autoEvents); 65 //GetGotelBase(entity); 66 //OTA_HotelDescriptiveInfo(entity.OTA_Hotel); 67 } 68 else 69 { 70 // Log.Info(string.Format("<h5 style='color:red;'>请求结束,城市:{0}出错了</h5>,时间:{1}<br>", city.CityName, DateTime.Now)); 71 Log.InfoFormat("基础信息:ResultCode:{0},ResultMsg:{1},SubCode:{2},SubMsg:{3}", entity.head.ResultCode, entity.head.ResultMsg, entity.head.SubCode, entity.head.SubMsg); 72 Log.InfoFormat("城市ID:{0},城市名称:{1} 的信息开始--", city.CityID, city.CityName); 73 Log.InfoFormat("返回信息:{0}", result); 74 } 75 Log.InfoFormat("请求接口,城市ID:{0},城市名称:{1} 的信息结束--", city.CityID, city.CityName); 76 77 } 78 } 79 catch (Exception ex) 80 { 81 Log.InfoFormat("获取城市信息异常:{0},堆栈:{1}", ex.Message, ex); 82 } 83 Log.Info("循环下载数据结束--"); 84 _timer.Start(); 85 } 86 87 } 88 89 public class Alpha 90 { 91 private static readonly ILog Log = LogManager.GetLogger("CtripHotelBaseInfoLog"); 92 public ManualResetEvent eventX; 93 public AutoResetEvent[] autoEvents; 94 public Alpha() 95 { 96 autoEvents = new AutoResetEvent[] 97 { 98 new AutoResetEvent(false), 99 new AutoResetEvent(false) 100 }; 101 eventX = new ManualResetEvent(false); 102 } 103 104 /// <summary> 105 /// 基本信息入库 106 /// </summary> 107 /// <param name="entity"></param> 108 public void GetGotelBase(object entity) 109 { 110 CtripHotelDataContext context = new CtripHotelDataContext(Settings.Default.CtripHotelConnectionString); 111 Log.Info("存入数据库开始--"); 112 context.Connection.Open(); 113 DbTransaction tran = context.Connection.BeginTransaction(); 114 context.Transaction = tran; 115 try 116 { 117 OTA_HotelSearchRSEntity en = (OTA_HotelSearchRSEntity)entity; 118 Ctrip_HotelBase hoteBase = null; 119 foreach (OTA_HotelEntity hotelEntity in en.OTA_Hotel) 120 { 121 122 } 123 context.SubmitChanges(); 124 tran.Commit(); 125 Log.Info("存入数据库结束--"); 126 eventX.Set(); 127 } 128 catch (Exception ex) 129 { 130 eventX.Set(); 131 Log.InfoFormat("基础信息入库异常:{0}", ex); 132 tran.Rollback(); 133 context.Connection.Close(); 134 context.Connection.Dispose(); 135 } 136 finally 137 { 138 context.Connection.Close(); 139 context.Connection.Dispose(); 140 } 141 } 142 143 /// <summary> 144 /// 请求详细信息 145 /// </summary> 146 /// <param name="entity"></param> 147 public void OTA_HotelDescriptiveInfo(object objhotelList) 148 { 149 Log.Info("请求详细信息开始--"); 150 try 151 { 152 eventX.WaitOne(); 153 string ss = string.Empty; 154 List<OTA_HotelEntity> hotelList = (List<OTA_HotelEntity>)objhotelList; 155 int pageIndex = 0; 156 int PageSize = 10; 157 int pageCount = (int)Math.Ceiling(hotelList.Count / (float)PageSize); 158 for (pageIndex = 0; pageIndex <= pageCount; pageIndex++) 159 { 160 OTA_HotelDescriptiveInfoRQEntity descriptiveInfoRqEntity = new OTA_HotelDescriptiveInfoRQEntity(); 161 descriptiveInfoRqEntity.OTA_HotelDescriptiveInfo = new List<OTA_HotelDescriptiveInfoEntity>(); 162 OTA_HotelDescriptiveInfoEntity descriptive = null; 163 string hotelId = string.Empty; 164 string hotelName = string.Empty; 165 foreach (OTA_HotelEntity hotelEntity in hotelList.Skip(pageIndex * PageSize).Take(PageSize)) 166 { 167 descriptive = new OTA_HotelDescriptiveInfoEntity(); 168 descriptive.HotelCode = hotelEntity.HotelCode.ToString(); 169 descriptive.AreaInfoSendAttractions = true; 170 descriptive.AreaInfoSendRecreations = true; 171 descriptive.ContactInfoSendData = true; 172 descriptive.FacilityInfoSendGuestRooms = true; 173 descriptive.HotelInfoSendData = true; 174 descriptive.MultimediaObjectsSendData = true; 175 descriptiveInfoRqEntity.OTA_HotelDescriptiveInfo.Add(descriptive); 176 hotelId += "," + hotelEntity.HotelCode; 177 hotelName += "," + hotelEntity.HotelName; 178 ss += "," + hotelId; 179 } 180 if (descriptiveInfoRqEntity == null || descriptiveInfoRqEntity.OTA_HotelDescriptiveInfo.Count == 0) 181 { 182 continue; 183 } 184 var serviceClient = new CtripHotelClient("CtripHotelService"); 185 string result = serviceClient.OTA_HotelDescriptiveInfoStr(descriptiveInfoRqEntity); 186 Thread.Sleep(2000); 187 if (string.IsNullOrEmpty(result)) 188 { 189 Log.Info("未获取到信息"); 190 return; 191 } 192 #region 193 #region 解析xml 194 195 #endregion 196 if (entity != null && entity.Head != null) 197 { 198 if (entity.Head.ResultCode != null && entity.Head.ResultCode.Equals("Success") 199 && entity.Head.SubCode != null && entity.Head.SubCode.Equals("Success") 200 && entity.HotelDescriptiveContent != null && entity.HotelDescriptiveContent.Count > 0) 201 { 202 //ThreadPool.QueueUserWorkItem(new WaitCallback(ImportHotelDescriptiveInfoWaitCall), entity); 203 GetHotelDescriptiveInfo(entity); 204 } 205 else 206 { 207 //Log.InfoFormat("详细信息出错,ID:{0},Name:{1},详细信息:ResultCode:{2},ResultMsg:{3},SubCode:{4},SubMsg:{5}", hotelEntity.HotelCode, hotelEntity.HotelName, 208 // entity.Head.ResultCode, entity.Head.ResultMsg, entity.Head.SubCode, entity.Head.SubMsg); 209 Log.InfoFormat("返回信息:{0}", result); 210 } 211 } 212 else 213 { 214 Log.InfoFormat("未请求到详细信息ID:{0},Name:{1}详细信息", hotelId, hotelName); 215 } 216 #endregion 217 } 218 Log.InfoFormat("计划循环执行完成:" + ss); 219 autoEvents[0].Set(); 220 autoEvents[0].Dispose(); 221 } 222 catch (Exception ex) 223 { 224 Log.InfoFormat("详细信息异常:{0}", ex); 225 } 226 Log.Info("请求详细信息完成"); 227 } 228 229 /// <summary> 230 /// 详细信息入库 231 /// </summary> 232 /// <param name="entity"></param> 233 private void GetHotelDescriptiveInfo(OTA_HotelDescriptiveInfoRSEntity entity) 234 { 235 #region 236 CtripHotelDataContext context = new CtripHotelDataContext(Settings.Default.CtripHotelConnectionString); 237 context.Connection.Open(); 238 DbTransaction tran = context.Connection.BeginTransaction(); 239 context.Transaction = tran; 240 try 241 { 242 Ctrip_HotelDescriptiveContent descriptiveResult = null; 243 //Log.InfoFormat("批量存入数据库开始共:{0}条记录--", entity.HotelDescriptiveContent.Count); 244 foreach (HotelDescriptiveContentEntity contentEntity in entity.HotelDescriptiveContent) 245 { 246 247 } 248 context.SubmitChanges(); 249 tran.Commit(); 250 //Log.Info("批量存入数据库结束--"); 251 } 252 catch (Exception ex) 253 { 254 Log.InfoFormat("详细信息入库异常:{0},堆栈:{1}", ex.Message, ex); 255 Log.InfoFormat("详细信息ID:{0},名称:{1}", entity.HotelDescriptiveContent[0].HotelCode, entity.HotelDescriptiveContent[0].HotelName); 256 tran.Rollback(); 257 context.Connection.Close(); 258 context.Connection.Dispose(); 259 } 260 finally 261 { 262 context.Connection.Close(); 263 context.Connection.Dispose(); 264 } 265 #endregion 266 } 267 268 public void OTA_HotelRatePlan(object objhotelList) 269 { 270 Log.Info("请求价格计划开始"); 271 eventX.WaitOne(); 272 string hotelCode = string.Empty; 273 string hotelName = string.Empty; 274 try 275 { 276 List<OTA_HotelEntity> hotelList = (List<OTA_HotelEntity>)objhotelList; 277 int pageIndex = 0; 278 int PageSize = 5; 279 int pageCount = (int)Math.Ceiling(hotelList.Count / (float)PageSize); 280 for (pageIndex = 0; pageIndex <= pageCount; pageIndex++) 281 { 282 OTA_HotelRatePlanRQEntity rqEntity = new OTA_HotelRatePlanRQEntity(); 283 rqEntity.RatePlan = new List<RatePlanRQEntity>(); 284 RatePlanRQEntity rateEntity = null; 285 foreach (OTA_HotelEntity hotelEntity in hotelList.Skip(pageIndex * PageSize).Take(PageSize)) 286 { 287 rateEntity = new RatePlanRQEntity(); 288 rateEntity.AvailRatesOnlyInd = true; 289 rateEntity.HotelCode = hotelEntity.HotelCode; 290 rateEntity.Start = DateTime.Now.Date; 291 rateEntity.End = rateEntity.Start.AddDays(28).Date; 292 rateEntity.RestrictedDisplayIndicator = "false"; 293 rqEntity.RatePlan.Add(rateEntity); 294 hotelCode += "," + hotelEntity.HotelCode; 295 hotelName += "," + hotelEntity.HotelName; 296 } 297 if (rqEntity == null || rqEntity.RatePlan.Count == 0) 298 { 299 continue; 300 } 301 var serviceClient = new CtripHotelClient("CtripHotelService"); 302 string result = serviceClient.OTA_HotelRatePlanStr(rqEntity); 303 Thread.Sleep(3000); 304 if (string.IsNullOrEmpty(result)) 305 { 306 Log.InfoFormat("未获取到ID:{0},名称:{1},价格信息信息", hotelCode, hotelName); 307 return; 308 } 309 OTA_HotelRatePlanRSEntity entity = new OTA_HotelRatePlanRSEntity(); 310 entity.Head = new HeadEntity(); 311 #region 解析xml 312 313 #endregion 314 if (entity != null && entity.Head != null) 315 { 316 if (entity.Head.ResultCode != null && entity.Head.ResultCode.Equals("Success") 317 && entity.Head.SubCode != null && entity.Head.SubCode.Equals("Success") 318 && entity.RatePlansList != null && entity.RatePlansList != null && entity.RatePlansList.Count > 0) 319 { 320 HotelRatePlanAdd(entity); 321 } 322 else 323 { 324 Log.InfoFormat("价格计划出错,ID:{0},Name:{1},详细信息:ResultCode:{2},ResultMsg:{3},SubCode:{4},SubMsg:{5}", hotelCode, hotelName, 325 entity.Head.ResultCode, entity.Head.ResultMsg, entity.Head.SubCode, entity.Head.SubMsg); 326 } 327 } 328 else 329 { 330 Log.InfoFormat("未请求到价格计划ID:{0},Name:{1}详细信息", hotelCode, hotelName); 331 } 332 } 333 autoEvents[1].Set(); 334 autoEvents[1].Dispose(); 335 } 336 catch (Exception ex) 337 { 338 Log.InfoFormat("请求价格计划异常:{0},堆栈:{1}", ex.Message, ex); 339 Log.InfoFormat("ID:{0},名称:{1},价格信息信息", hotelCode, hotelName); 340 } 341 Log.Info("请求价格计划完成"); 342 } 343 344 345 /// <summary> 346 /// 初始化价格入库 347 /// </summary> 348 /// <param name="entity"></param> 349 private void HotelRatePlanAdd(OTA_HotelRatePlanRSEntity entity) 350 { 351 CtripHotelDataContext context = new CtripHotelDataContext(Settings.Default.CtripHotelConnectionString); 352 context.Connection.Open(); 353 DbTransaction tran = context.Connection.BeginTransaction(); 354 context.Transaction = tran; 355 string hotelCode = string.Empty; 356 try 357 { 358 Ctrip_HotelRatePlan ratePlan = null; 359 foreach (RatePlanSRSEntity ratePlansEntity in entity.RatePlansList) 360 { 361 362 } 363 context.SubmitChanges(); 364 tran.Commit(); 365 } 366 catch (Exception ex) 367 { 368 Log.InfoFormat("名称:{0}价格计划入库异常:{1};", hotelCode, ex); 369 tran.Rollback(); 370 context.Connection.Close(); 371 context.Connection.Dispose(); 372 } 373 finally 374 { 375 context.Connection.Close(); 376 context.Connection.Dispose(); 377 } 378 } 379 }
具体原因是什么我也不清楚,但我用别人封装的方法,不会出现不执行的情况。发给你参考下
public class OverTimeCntrol { public delegate void Delegate(); /// <summary> /// 执行指定的方法,如果在指定的时间之内没有完成,则中止 /// </summary> /// <param name="func">任务过程</param> /// <param name="timeSpan">超时时间</param> /// <param name="timeoutCallback">如果超时,则调用该方法</param> /// <returns>是否正确执行完毕</returns> public static bool CallFuncThread(Delegate func, TimeSpan timeSpan, Delegate timeoutCallback) { if (func == null) throw new ArgumentNullException("func"); ManualResetEvent resetEvent = new ManualResetEvent(false); ManualResetEvent waitThreadEvent = new ManualResetEvent(false); Exception error = null; Thread thread = null; // 将任务加到线程当中 ThreadPool.QueueUserWorkItem(delegate { thread = Thread.CurrentThread; try { func(); } catch (ThreadAbortException) { } catch (Exception ex) { error = ex; } resetEvent.Set(); waitThreadEvent.WaitOne(); // 每次线程执行结束都等待后续的处理逻辑 }); try { bool result = resetEvent.WaitOne(timeSpan, false); // 等待任务的结束 if (error != null) // 说明在执行过程中出现异常,直接抛出异常 throw error; if (!result) { if (thread != null) { thread.Abort(); // 此时可以确保该线程没有开始运行新的任务 waitThreadEvent.Set(); } if (timeoutCallback != null) timeoutCallback(); } return result; } finally { waitThreadEvent.Set(); // 最后确保释放线程池线程 } } }
谢谢你帮忙
原因找到了,我写的线程池没有问题,问题是我代码中循环太多,有个地方return掉了,应该break就对了。
在线程窗口里面双击C的线程,看看C线程在什么地方停止运行了,再看看周围是否有可能出现死循环吧
另外可以使用Thread.CurrentThread.ThreadState在watch窗口(ctrl+D+Q)上看看当前线程的状态