首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 关于多线程的问题,高手们帮帮忙。 [已结贴,结贴人:fox54088]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • fox54088
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    • 揭帖率:
    发表于:2008-07-23 21:04:56 楼主
    今天在处理一个问题,就是为会员生成目录的问题,但是系统现在注册的会员有20万人,也就是要生成20万个文件夹。一开始没用多线程的时候,电脑直接卡机,现在改用多线程来处理。代码如下:
    public class FoxThread
        {
            public FoxThread()
            {

            }
            public FoxThread(int currentPage, int showCount, string swhere)
            {
                this.currengPage = currentPage;
                this.showCount = showCount;
                this.swhere = swhere;
            }
            private Thread myThread;

            public Thread MyThread
            {
                get { return myThread; }
                set { myThread = value; }
            }
            public void StartThread()
            {
                myThread = new Thread(new ThreadStart(RunFunction));
                myThread.Start();
            }
            private string connectString = "data source=(local);database=fox;uid=sa;pwd=123";
            /// <summary>
            /// 总的记录数
            /// </summary>
            private int recordCount = 0;

            public int RecordCount
            {
                get { return recordCount; }
                set { recordCount = value; }
            }
            private int currengPage = 1;

            public int CurrengPage
            {
                get { return currengPage; }
                set { currengPage = value; }
            }
            /// <summary>
            /// 每页显示字段
            /// </summary>
            private int showCount;

            public int ShowCount
            {
                get { return showCount; }
                set { showCount = value; }
            }
            private string swhere;

            public string Swhere
            {
                get { return swhere; }
                set { swhere = value; }
            }
            private DataTable dtRecord;

            public DataTable DtRecord
            {
                get { return dtRecord; }
                set { dtRecord = value; }
            }

            public void RunFunction()
            {
                SqlConnection lvConn = new SqlConnection(connectString);
                lvConn.Open();
                SqlCommand lvCmd = new SqlCommand("[Page_PROC]", lvConn);//调用的存储过程
                lvCmd.CommandType = CommandType.StoredProcedure;
                SqlParameter[] parameters = {
                        new SqlParameter("@TblName",SqlDbType.VarChar),
                        new SqlParameter("@ID",SqlDbType.VarChar),
                        new SqlParameter("@CurrentPage",SqlDbType.Int),
                        new SqlParameter("@PageSize",SqlDbType.Int),
                        new SqlParameter("@FldName",SqlDbType.VarChar),
                        new SqlParameter("@OrderType",SqlDbType.Int),
                        new SqlParameter("@StrWhere",SqlDbType.VarChar)
                 
                        };
                parameters[0].Value = "users";//表名,这里是乱取的
                parameters[1].Value = "localn";
                parameters[2].Value = currengPage;
                parameters[3].Value = showCount;
                parameters[4].Value = "luckey_num,maketime";
                parameters[5].Value = 1;
                parameters[6].Value = swhere;

                foreach (SqlParameter parm in parameters)
                {
                    lvCmd.Parameters.Add(parm);
                }
                SqlDataAdapter lvApter = new SqlDataAdapter(lvCmd);
                DataSet ds = new DataSet();
                lvApter.Fill(ds, "users");
                if (ds != null)
                {
                    DataTable dt = ds.Tables[0];
                    for (int j = 0; j < dt.Rows.Count; j++)
                    {
                        string gg = dt.Rows[j][1].ToString();
                        DateTime dd = DateTime.Parse(dt.Rows[j][1].ToString());
                        FolderCreate(dd.Year + "\\" + dd.Month + "\\" + dd.Day + "\\" + dt.Rows[j][0].ToString());
                    }
                }
       
                lvConn.Close();
                lvCmd.Dispose();
                lvConn.Dispose();
            }

            public static void FolderCreate(string Path)
            {
                // 判断目标目录是否存在如果不存在则新建之
                if (!Directory.Exists(Path))
                    Directory.CreateDirectory(Path);
            }

    然后在主程序中调用
      RecordCount = dt.Rows.Count;
                int showCount = 5000;

                int currentPage = 1;
                int allPage=0;
                    allPage=RecordCount%showCount==0?RecordCount/showCount:RecordCount/showCount+1;
              if(allPage <=0)
                  return;
              for (int i = currentPage; i < allPage; i++)
              {
                  FoxThread otherThread = new FoxThread(i, showCount, "");
                  otherThread.StartThread();
              }
    我是想通过像存储过程分页那样来生成线程,但是这样电脑还是很卡,有没有什么可以优化的方法,希望高手不吝赐教。
    分数不够在加。
    100  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • jiangsheng
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    发表于:2008-07-24 06:33:191楼 得分:0
    多分几层,每层目录数不要太多,几百个就可以
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • yulinlover
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    发表于:2008-07-24 08:25:022楼 得分:20
    请你不要在线程里频繁创建SQL的连接,会把你的连接池耗光的,请小心,我在一ERP项目里发现前人写的一个网络控制的函数也是这样去循环调用,执行1000条数据操作的时候,立刻死机。所以这里给你几点建议:
    1、不要在线程里同物理设备或其它物理资源打交道(频繁释放资源和占用资源很慢的)
    2、建议在存储过程里进行批处理(SQL里最好的就是进行批处理,这样SQL执行计划会自己帮你优化好大一部分),坚决抵制循环调用数据库
    3、建议把SQL执行后的结果,以数据或集合的方式传出来,然后另开一个线程去建立所谓的目录。而不要把建立目录放在每一个循环里做。

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • yilanwuyu123
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    发表于:2008-07-24 08:31:353楼 得分:0
    mark
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • yilanwuyu123
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    发表于:2008-07-24 08:35:524楼 得分:0
    mark
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • kbryant
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    • 3

    发表于:2008-07-24 08:37:075楼 得分:0
    友情帮顶
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • downmoon
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    发表于:2008-07-24 08:55:256楼 得分:0
    引用 2 楼 yulinlover 的回复:
    3建议把SQL执行后的结果,以数据或集合的方式传出来,然后另开一个线程去建立所谓的目录。而不要把建立目录放在每一个循环里做。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • mzmxchenweij
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    发表于:2008-07-24 09:05:567楼 得分:0
    引用 2 楼 yulinlover 的回复:

    2、建议在存储过程里进行批处理(SQL里最好的就是进行批处理,这样SQL执行计划会自己帮你优化好大一部分),坚决抵制循环调用数据库

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • virusplayer
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    发表于:2008-07-24 09:21:458楼 得分:0
    使用存储过程分页吧,那样会提高执行的效率
    CREATE procedure main_table_pwqzc
    (@pagesize int,
    @pageindex int,
    @docount bit,
    @this_id)
    as
    if(@docount=1)
    begin
    select count(id) from luntan where this_id=@this_id
    end
    else
    begin
    declare @indextable table(id int identity(1,1),nid int)
    declare @PageLowerBound int
    declare @PageUpperBound int
    set @PageLowerBound=(@pageindex-1)*@pagesize
    set @PageUpperBound=@PageLowerBound+@pagesize
    set rowcount @PageUpperBound
    insert into @indextable(nid) select id from luntan where this_id=@this_id order by reply_time desc
    select a.* from luntan a,@indextable t where a.id=t.nid
    and t.id>@PageLowerBound and t.id <=@PageUpperBound order by t.id
    end
    GO

    存储过程会根据传入的参数@docount来确定是不是要返回所有要分页的记录总数
    特别是这两行

    set rowcount @PageUpperBound
    insert into @indextable(nid) select id from luntan where this_id=@this_id order by reply_time desc

    真的是妙不可言!!set rowcount @PageUpperBound当记录数达到@PageUpperBound时就会停止处理查询
    ,select id 只把id列取出放到临时表里,select a.* from luntan a,@indextable t where a.id=t.nid
    and t.id>@PageLowerBound and t.id <=@PageUpperBound order by t.id 而这句也只从表中取出所需要的记录,而不是所有的记录,结合起来,极大的提高了效率!!
    妙啊,真的妙!!!!

    CREATE PROCEDURE Paging_RowCount
    (
    @Tables varchar(1000),
    @PK varchar(100),
    @Sort varchar(200) = NULL,
    @PageNumber int = 1,
    @PageSize int = 10,
    @Fields varchar(1000) = '*',
    @Filter varchar(1000) = NULL,
    @Group varchar(1000) = NULL)
    AS

    /*Default Sorting*/
    IF @Sort IS NULL OR @Sort = ''
    SET @Sort = @PK

    /*Find the @PK type*/
    DECLARE @SortTable varchar(100)
    DECLARE @SortName varchar(100)
    DECLARE @strSortColumn varchar(200)
    DECLARE @operator char(2)
    DECLARE @type varchar(100)
    DECLARE @prec int

    /*Set sorting variables.*/
    IF CHARINDEX('DESC',@Sort)>0
    BEGIN
    SET @strSortColumn = REPLACE(@Sort, 'DESC', '')
    SET @operator = ' <='
    END
    ELSE
    BEGIN
    IF CHARINDEX('ASC', @Sort) = 0
    SET @strSortColumn = REPLACE(@Sort, 'ASC', '')
    SET @operator = '>='
    END


    IF CHARINDEX('.', @strSortColumn) > 0
    BEGIN
    SET @SortTable = SUBSTRING(@strSortColumn, 0, CHARINDEX('.',@strSortColumn))
    SET @SortName = SUBSTRING(@strSortColumn, CHARINDEX('.',@strSortColumn) + 1, LEN(@strSortColumn))
    END
    ELSE
    BEGIN
    SET @SortTable = @Tables
    SET @SortName = @strSortColumn
    END

    SELECT @type=t.name, @prec=c.prec
    FROM sysobjects o
    JOIN syscolumns c on o.id=c.id
    JOIN systypes t on c.xusertype=t.xusertype
    WHERE o.name = @SortTable AND c.name = @SortName

    IF CHARINDEX('char', @type) > 0
    SET @type = @type + '(' + CAST(@prec AS varchar) + ')'

    DECLARE @strPageSize varchar(50)
    DECLARE @strStartRow varchar(50)
    DECLARE @strFilter varchar(1000)
    DECLARE @strSimpleFilter varchar(1000)
    DECLARE @strGroup varchar(1000)

    /*Default Page Number*/
    IF @PageNumber < 1
    SET @PageNumber = 1

    /*Set paging variables.*/
    SET @strPageSize = CAST(@PageSize AS varchar(50))
    SET @strStartRow = CAST(((@PageNumber - 1)*@PageSize + 1) AS varchar(50))

    /*Set filter & group variables.*/
    IF @Filter IS NOT NULL AND @Filter != ''
    BEGIN
    SET @strFilter = ' WHERE ' + @Filter + ' '
    SET @strSimpleFilter = ' AND ' + @Filter + ' '
    END
    ELSE
    BEGIN
    SET @strSimpleFilter = ''
    SET @strFilter = ''
    END
    IF @Group IS NOT NULL AND @Group != ''
    SET @strGroup = ' GROUP BY ' + @Group + ' '
    ELSE
    SET @strGroup = ''

    /*Execute dynamic query*/
    EXEC(
    '
    DECLARE @SortColumn ' + @type + '
    SET ROWCOUNT ' + @strStartRow + '
    SELECT @SortColumn=' + @strSortColumn + ' FROM ' + @Tables + @strFilter + ' ' + @strGroup + ' ORDER BY ' + @Sort + '
    SET ROWCOUNT ' + @strPageSize + '
    SELECT ' + @Fields + ' FROM ' + @Tables + ' WHERE ' + @strSortColumn + @operator + ' @SortColumn ' + @strSimpleFilter + ' ' + @strGroup + ' ORDER BY ' + @Sort + '
    '
    )
    GO
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • fox54088
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    发表于:2008-07-24 09:31:499楼 得分:0
    我那个就是使用存储过程分页,
    楼上说的会把线程池的资源用关,我已经遇到了,确实是很容易死机,因为那样就差不多要创建40个线程,进行40次连接和释放。可是有没有一些具体的方案。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hillspring
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    发表于:2008-07-24 09:35:0110楼 得分:0
    mark
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • Tll_W
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    发表于:2008-07-24 09:57:0511楼 得分:0
    学到了不少东西呢,一般线程中确实不要牵涉到资源类的东西,用到了就在外面定义,里面用就行了。。。

    存储过程分页。。。。学习
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • sxmonsy
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    发表于:2008-07-24 10:00:1612楼 得分:0
    我来接点分能接到吗?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • fox54088
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    发表于:2008-07-24 10:20:3413楼 得分:0
    分数不是问题,我现在用事务来处理,把所有的语句放在hasttable里,然后调用存储过程分页,这样就返回一个dataset,然后在用多线程对返回的 dataset里的table进行处理。
    这样连接就只要一次。


    但是,有没有人能说下,如何查看使用多线程能提高多少效率,如何查看,或者说通过编写代码查看,像现在这样我就定义了40个线程,但这样比没使用线程快多少,还是几乎没提高。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhzuo
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    发表于:2008-07-24 19:27:3814楼 得分:80
    建议楼主可以试一下类似于BackgroundWorker组件的来进行异步处理。
    关于这方面的资料可以看这里,我写了一些东西。
    http://blog.csdn.net/zhzuo/archive/2008/07/23/2699305.aspx
    http://blog.csdn.net/zhzuo/archive/2008/07/23/2699847.aspx
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhzuo
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    发表于:2008-07-24 19:29:5715楼 得分:0
    另外,目录太多是不是可以合理的组织简化一下,比如按地区,按性别,或按其他素,而不是每个人一个文件夹。还有对文件夹文件建立Windows索引,搜索效果会好很多。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • fox54088
    • 等级:
    • 可用分等级:
    • 总技术专家分:
    • 总技术专家分排名:
    发表于:2008-07-25 10:42:1316楼 得分:0
    好的谢谢了
    修改 删除 举报 引用 回复

    网站简介广告服务网站地图帮助联系方式诚聘英才English 问题报告
    北京创新乐知广告有限公司 版权所有 京 ICP 证 070598 号
    世纪乐知(北京)网络技术有限公司 提供技术支持
    Copyright © 2000-2008, CSDN.NET, All Rights Reserved