首页 新闻 会员 周边

高分求解:windows服务定时执行,占用大量内存

0
悬赏园豆:80 [已解决问题] 解决于 2014-08-07 13:26

如题,最近做了个定时任务的服务,代码片段如下:

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;
        }

 


求解决方案

问题补充:

下面把补充的代码贴出来

 

ds.Clear();
ds=null;
System.GC.Collect();

赶猪上架的主页 赶猪上架 | 初学一级 | 园豆:6
提问于:2014-08-06 18:06
< >
分享
最佳答案
0

可以先检查下你的逻辑代码有没有内存泄漏。主要看有没有调用非托管资源,比如网络,IO等。

收获园豆:80
XiaoFaye | 老鸟四级 |园豆:3087 | 2014-08-06 18:13

这个逻辑代码的主要功能就是"爬虫"机制,会访问某个网站,抓取信息

赶猪上架 | 园豆:6 (初学一级) | 2014-08-06 18:17

会不会是这里面我写了几个dataset数据集,用完之后没有释放?

赶猪上架 | 园豆:6 (初学一级) | 2014-08-06 18:20

@ganzhushangjia: 

那就要检查下这些对象有没有被正确释放了,特别是stream,在finally显式调用。

另外网络访问本身就比较占资源的,你不见IE开10个网页都卡吗?好奇你一下子开几个线程。

XiaoFaye | 园豆:3087 (老鸟四级) | 2014-08-06 18:22

@ganzhushangjia: 

晕。。。dataset是把所有数据放内存里的。。。如果访问很多数据的话换datareader吧。

XiaoFaye | 园豆:3087 (老鸟四级) | 2014-08-06 18:23

@XiaoFaye: 补充的代码已经贴出来了

赶猪上架 | 园豆:6 (初学一级) | 2014-08-07 09:24

@ganzhushangjia: 

首先,这么大量的字符串操作,请用stringbuilder

XiaoFaye | 园豆:3087 (老鸟四级) | 2014-08-07 09:45

@ganzhushangjia: 

看你的数据库只取一条记录出来,那应该跟dataset关系不大。另外,你自己看看有没有打开过多页面了。你的是1秒执行一次,每次打开几个页面?

XiaoFaye | 园豆:3087 (老鸟四级) | 2014-08-07 09:59

@XiaoFaye: 只打开一个页面没相隔20秒促发一次,每个执行都是一个独立的线程,互补相干,不是排队模式

赶猪上架 | 园豆:6 (初学一级) | 2014-08-07 11:07

@ganzhushangjia: 

你说的大量占用内存,到底是占用多少?程序运行前剩余内存多少?运行5分钟后占用多少?

XiaoFaye | 园豆:3087 (老鸟四级) | 2014-08-07 11:18

@XiaoFaye: 初始化内存占用:2435,5秒后:14555,每隔20秒增加100

赶猪上架 | 园豆:6 (初学一级) | 2014-08-07 12:27

@ganzhushangjia: 

我觉得在这里你可以用排队法:

第一步是把所有数据库相关的操作注释了,不读取,不写入。然后看内存占用怎么样。不行再继续第二步。

第二步把页面操作相关的语句注释,也就是说程序只获取页面,但是不做任何处理。

这样下来应该就能把原因定位在某个地方了,然后再查具体原因。

XiaoFaye | 园豆:3087 (老鸟四级) | 2014-08-07 13:07
其他回答(3)
0

你贴出来的代码都是无助于解决问题的,问题出在你没贴出来的代码。

爱编程的大叔 | 园豆:30839 (高人七级) | 2014-08-06 21:01

补充的代码已经贴出来了

支持(0) 反对(0) 赶猪上架 | 园豆:6 (初学一级) | 2014-08-07 09:24
0

应该是访问之后,没有释放stream吧。如果是dataset占用太多内存,那就要考虑,分阶段存储到硬盘了。

forhells | 园豆:724 (小虾三级) | 2014-08-06 21:53

补充的代码已经贴出来了

支持(0) 反对(0) 赶猪上架 | 园豆:6 (初学一级) | 2014-08-07 09:24
0

楼主用的timer不对吧,应该用system.timers.timer ,此外,楼上已经说过了IO操作要及时清理非托管资源来释放内存.还是尽量使用异步操作吧,避免过多等待

我不是杰克船长 | 园豆:238 (菜鸟二级) | 2014-08-07 13:24
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册