如题,最近做了个定时任务的服务,代码片段如下:
private System.Threading.Timer timerClose; /// <summary> protected override void OnStart(string[] args) { // TODO: 在此处添加代码以启动服务。 //5秒后开始运行,接着每隔1秒的调用Tick方法 // Create a timer thread and start it timerClose = new System.Threading.Timer(new TimerCallback(DoSomething), this, 20000, 20000); }
private bool IsAotuStarTime(string State, string OnceDateBegin) { bool resultflag = false; //未抓取 if (State == "0") { resultflag = true; return resultflag; } else if (State == "1") { return resultflag; } else { DateTime d = Convert.ToDateTime(DateTime.Now.ToShortDateString()); DateTime t = Convert.ToDateTime(Convert.ToDateTime(OnceDateBegin).ToShortDateString()); //达到时间要求 if (d == t) { return resultflag; } else { resultflag = true; return resultflag; } } } private void DoSomething(object source) { int pagesize = 10; DataSet ds = DbHelperSQL.Query("select top 1 ID,GoodsID,BeMonitoredGoodsID,KeyWord,Wangwang,MonitoringTime,State from [KeywordsMonitoring] where IsBegin=1 and State<>1"+ " and (Convert(date,MonitoringTime)<> Convert(date,GETDATE()) or MonitoringTime is null) order by MonitoringTime "); if (ds.Tables[0].Rows.Count > 0) { //初始化排名 int paiming = 0; string KeyWordID = ds.Tables[0].Rows[0]["ID"].ToString(); string GoodsID = ds.Tables[0].Rows[0]["BeMonitoredGoodsID"].ToString(); if (GoodsID=="") { GoodsID = ds.Tables[0].Rows[0]["GoodsID"].ToString(); } string KeyWord = ds.Tables[0].Rows[0]["KeyWord"].ToString(); string Wangwang = ds.Tables[0].Rows[0]["Wangwang"].ToString(); string MonitoringTime =""; if (ds.Tables[0].Rows[0]["MonitoringTime"].ToString()!="") { MonitoringTime = ds.Tables[0].Rows[0]["MonitoringTime"].ToString(); } string State = ds.Tables[0].Rows[0]["State"].ToString(); if (IsAotuStarTime(State,MonitoringTime)) { DbHelperSQL.ExecuteSqlByTime("update [KeywordsMonitoring] set State=1 where ID=" + KeyWordID, 0); string newkey = HttpUtility.UrlEncode(System.Text.ASCIIEncoding.GetEncoding("gb2312").GetBytes(KeyWord)); string URL = "http://s.taobao.com/search?q=" + newkey + "&tab=all&bcoffset=1&s=0"; //获取到源文件代码 string MainHtml = GetMethodHtml(URL); //if (MainHtml=="") //{ // continue; //} //截取产品列表 string[] resultString = Regex.Split(MainHtml, "<div class=\"col item st-item icon-datalink \" nid", RegexOptions.IgnoreCase); for (int i = 0; i < resultString.Length; i++) { if (!resultString[i].ToString().Contains("进入怪异模式")) { paiming += 1; if (resultString[i].ToString().Contains(GoodsID)) { DbHelperSQL.ExecuteSqlByTime("insert into [MonitoringDetail](KeyWordID,MonitoringTime,Ranking)values(" + KeyWordID + ",getdate()," + paiming + ")", 0); DbHelperSQL.ExecuteSqlByTime("update [KeywordsMonitoring] set MonitoringTime=getdate(),Ranking=" + paiming + ",State=2 where ID=" + KeyWordID, 0); //timerClose.Dispose(); paiming = 0; return; } } } //默认每页44个 int page = pagesize - 1; while (page < pagesize && page > 0) { string pageURL = "http://s.taobao.com" + NewMethodPage(URL);//StrBtest(MainHtml, "<span class=\"icon-btn-prev-2-disable\"></span> </a><a href=\"", "\" class=\"page-next\" trace='srp_select_pagedown'>"); MainHtml = GetMethodHtml(pageURL); resultString = Regex.Split(MainHtml, "<div class=\"col item st-item icon-datalink \" nid", RegexOptions.IgnoreCase); for (int i = 0; i < resultString.Length; i++) { if (!resultString[i].ToString().Contains("进入怪异模式")) { paiming += 1; if (resultString[i].ToString().Contains(GoodsID)) { DbHelperSQL.ExecuteSqlByTime("insert into [MonitoringDetail](KeyWordID,MonitoringTime,Ranking)values(" + KeyWordID + ",getdate()," + paiming + ")", 0); DbHelperSQL.ExecuteSqlByTime("update [KeywordsMonitoring] set MonitoringTime=getdate(),Ranking=" + paiming + ",State=2 where ID=" + KeyWordID, 0); //timerClose.Dispose(); paiming = 0; return; } } } page--; if (page == 0) { DbHelperSQL.ExecuteSqlByTime("insert into [MonitoringDetail](KeyWordID,MonitoringTime,Ranking)values(" + KeyWordID + ",getdate()," + paiming + ")", 0); DbHelperSQL.ExecuteSqlByTime("update [KeywordsMonitoring] set MonitoringTime=getdate(),Ranking=" + paiming + ",State=2 where ID=" + KeyWordID, 0); // DbHelperSQL.Query("select KesyWorld "); //timerClose.Dispose(); return; } URL = "http://s.taobao.com" + NewMethodPage(URL); } } //timerClose.Dispose(); } } /// <summary> /// 获取分页链接地址 /// </summary> /// <param name="URL"></param> /// <returns></returns> private string NewMethodPage(string URL) { HttpHelper http = new HttpHelper(); HttpItem item = new HttpItem() { URL = URL, //URL 必需项 Method = "get",//URL 可选项 默认为Get IsToLower = false,//得到的HTML代码是否转成小写 可选项默认转小写 Cookie = "",//字符串Cookie 可选项 Referer = "",//来源URL 可选项 Postdata = "",//Post数据 可选项GET时不需要写 Timeout = 100000,//连接超时时间 可选项默认为100000 ReadWriteTimeout = 30000,//写入Post数据超时时间 可选项默认为30000 UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",//用户的浏览器类型,版本,操作系统 可选项有默认值 ContentType = "text/html",//返回类型 可选项有默认值 Allowautoredirect = false,//是否根据301跳转 可选项 //CerPath = "d:\123.cer",//证书绝对路径 可选项不需要证书时可以不写这个参数 //Connectionlimit = 1024,//最大连接数 可选项 默认为1024 ProxyIp = "",//代理服务器ID 可选项 不需要代理 时可以不设置这三个参数 //ProxyPwd = "123456",//代理服务器密码 可选项 //ProxyUserName = "administrator",//代理服务器账户名 可选项 }; HttpResult result = http.GetHtml(item); string html = result.Html; string cookie = result.Cookie; if (html.Contains("本次请求并未返回任何数据")) { return ""; } else if (html.Contains("操作已超时")) { return ""; } //获取信息总表HTML string MainHtml = StrBtest(html, "<span class=\"icon-btn-prev-2-disable\"></span> </a><a href=\"", "\" class=\"page-next\" trace='srp_select_pagedown'>"); if (MainHtml == "") { MainHtml = StrBtest(html, "<span class=\"icon-btn-prev-2\"></span></a><a href=\"", "\" class=\"page-next\" trace='srp_select_pagedown'>"); } //分页地址 return MainHtml; } /// <summary> /// 截取字符串方法 /// </summary> /// <param name="buttonSubmit"></param> /// <param name="begion"></param> /// <param name="last"></param> /// <returns></returns> private string StrBtest(string buttonSubmit, string begion, string last) { string strDest = ""; try { int beginIndex = buttonSubmit.IndexOf(begion); if (beginIndex <= 0) { return ""; } string newstr = buttonSubmit.Substring(beginIndex, (buttonSubmit.Length - beginIndex)); int endIndex = newstr.IndexOf(last); if (endIndex <= 0) { return ""; } strDest = newstr.Substring(begion.Length, endIndex - begion.Length); } catch (Exception es) { return es.ToString() ; } return strDest; } private string StrBtestPage(string buttonSubmit, string begion) { string strDest = ""; try { string last = "\">"; int beginIndex = buttonSubmit.IndexOf(begion); if (beginIndex <= 0) { return ""; } string newstr = buttonSubmit.Substring(beginIndex, (buttonSubmit.Length - beginIndex)); int nowIndex = newstr.IndexOf(begion); int endIndex = newstr.IndexOf(last); if (endIndex < 0) { endIndex = newstr.IndexOf("\" data-spm-anchor-id="); } strDest = newstr.Substring(begion.Length, endIndex - begion.Length); } catch (Exception es) { return es.ToString(); } return strDest; } /// 根据url地址获取宝贝源代码 /// </summary> /// <param name="URL"></param> /// <returns></returns> private string GetMethodHtml(string URL) { HttpHelper http = new HttpHelper(); HttpItem item = new HttpItem() { URL = URL, Method = "get",//URL 可选项 默认为Get IsToLower = false,//得到的HTML代码是否转成小写 可选项默认转小写 Cookie = "",//字符串Cookie 可选项 Referer = "",//来源URL 可选项 Postdata = "",//Post数据 可选项GET时不需要写 Timeout = 100000,//连接超时时间 可选项默认为100000 ReadWriteTimeout = 30000,//写入Post数据超时时间 可选项默认为30000 UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",//用户的浏览器类型,版本,操作系统 可选项有默认值 ContentType = "text/html",//返回类型 可选项有默认值 Allowautoredirect = false,//是否根据301跳转 可选项 ProxyIp = "",//代理服务器ID 可选项 不需要代理 时可以不设置这三个参数 }; HttpResult result = http.GetHtml(item); string html = result.Html; string cookie = result.Cookie; if (html.Contains("本次请求并未返回任何数据")) { return null; } return html; }
求解决方案
可以先检查下你的逻辑代码有没有内存泄漏。主要看有没有调用非托管资源,比如网络,IO等。
这个逻辑代码的主要功能就是"爬虫"机制,会访问某个网站,抓取信息
会不会是这里面我写了几个dataset数据集,用完之后没有释放?
@ganzhushangjia:
那就要检查下这些对象有没有被正确释放了,特别是stream,在finally显式调用。
另外网络访问本身就比较占资源的,你不见IE开10个网页都卡吗?好奇你一下子开几个线程。
@ganzhushangjia:
晕。。。dataset是把所有数据放内存里的。。。如果访问很多数据的话换datareader吧。
@XiaoFaye: 补充的代码已经贴出来了
@ganzhushangjia:
首先,这么大量的字符串操作,请用stringbuilder
@ganzhushangjia:
看你的数据库只取一条记录出来,那应该跟dataset关系不大。另外,你自己看看有没有打开过多页面了。你的是1秒执行一次,每次打开几个页面?
@XiaoFaye: 只打开一个页面没相隔20秒促发一次,每个执行都是一个独立的线程,互补相干,不是排队模式
@ganzhushangjia:
你说的大量占用内存,到底是占用多少?程序运行前剩余内存多少?运行5分钟后占用多少?
@XiaoFaye: 初始化内存占用:2435,5秒后:14555,每隔20秒增加100
@ganzhushangjia:
我觉得在这里你可以用排队法:
第一步是把所有数据库相关的操作注释了,不读取,不写入。然后看内存占用怎么样。不行再继续第二步。
第二步把页面操作相关的语句注释,也就是说程序只获取页面,但是不做任何处理。
这样下来应该就能把原因定位在某个地方了,然后再查具体原因。
你贴出来的代码都是无助于解决问题的,问题出在你没贴出来的代码。
补充的代码已经贴出来了
应该是访问之后,没有释放stream吧。如果是dataset占用太多内存,那就要考虑,分阶段存储到硬盘了。
补充的代码已经贴出来了
楼主用的timer不对吧,应该用system.timers.timer ,此外,楼上已经说过了IO操作要及时清理非托管资源来释放内存.还是尽量使用异步操作吧,避免过多等待