List<ErrorModel> errorList = new List<ErrorModel>();
        static ManualResetEvent[] ThreadEvent = new ManualResetEvent[10];//线程事件        public void MakeHtmlByThread(out IList<ErrorModel> Errors, IList<PathModel> pathModels)
        {            int count = pathModels.Count / 10;            for (int i = 0; i < 10; i++)    //将任务分发给10个支线程
            {
                ThreadEvent[i] = new ManualResetEvent(false);
                ThreadPool.QueueUserWorkItem(delegate { ToHtml(pathModels.Skip(count * i).Take(count).ToList<PathModel>(), ThreadEvent[i]); });
            }
            WaitHandle.WaitAll(ThreadEvent);    //等待所有支线程结束            Errors = errorList;
        }        private void ToHtml(IList<PathModel> modelList, ManualResetEvent _theradEvent)
        {
            foreach (PathModel model in modelList)
            {
                Stopwatch watch = Stopwatch.StartNew();
                try
                {
                    string url = "http://" + Request.UrlReferrer.Authority + Request.ApplicationPath + model.aspxPath;
                    string html = model.htmlPath;
                    if (html.EndsWith(".html"))
                    {
                        int dot = html.LastIndexOf(".html");
                        int index = html.LastIndexOf("/") + 1;
                        string s1 = html.Substring(0, index);
                        string s2 = html.Substring(index, dot - index);
                        string fileDir = ZH.FileControl.FileBuild.BuildHtmls(url, Request.PhysicalApplicationPath, s1, s2);
                    }
                }
                catch (Exception ex)
                {
                    errorList.Add(new ErrorModel() { errorMsg = Thread.CurrentThread.Name + "号线程执行的任务包含错误:" + ex.Message + ",耗时:" + watch.Elapsed.TotalSeconds + "秒。", id = model.id });
                }
            }            if (null != _theradEvent) _theradEvent.Set();//指示本线程已结束
        }
这段代码是用多线程生成静态页面,其中:MakeHtmlByThread方式启动了10个线程,每个,但是ThreadPool.QueueUserWorkItem(delegate { ToHtml(pathModels.Skip(count * i).Take(count).ToList<PathModel>(), ThreadEvent[i]); }此处却每次都提示数组超出索引,我调试看,发现i居然等于10了怎么解决这个问题?是什么原因导致?
而且我发现我只要规规矩矩的按F10单步调试,是不会出现这种问题的,但是我只要正常运行,或者按F5跳过,就会出现这种问题。
是多线程导致的吗?怎么解决?

解决方案 »

  1.   

    不是i从几开始,你看清楚,我循环的条件是i<10,而不是i<=10,那么循环内部怎么可能出现i=10的时候。
      

  2.   

    和多线程没关系,你调试到第八次时仔细看下i的值,和你那个数组的个数问题是有点怪,至少i为10不会进入循环嘛还有就是调试要是一步一步就正常,我觉得这个应该不对,你把代码重新生成一下然后调试到最后一次在仔细看下i的值和数组的个数
      

  3.   

    不清楚
     当i=9 的时候 后边i++ 这样i就等于10了 但是等于10的时候会跳出循环啊 
    难道没有跳吗
      

  4.   

    我大概猜到原因了,多线程问题,ThreadPool.QueueUserWorkItem(delegate { ToHtml(pathModels.Skip(count * i).Take(count).ToList<PathModel>(), ThreadEvent[i]); }最后一次执行这句是,循环已经退出,此时i=10,然而因为多线程,在循环退出后才执行了这句代码。所以此时i等于10了,然后抛异常。那么怎么解决这个问题呢?
      

  5.   

    for (int i = 0; i < 10; i++) 
    最後推出循環的時候是,1不就是等於10嗎?
      

  6.   


            private System.Object lockThis = new System.Object();
            public void MakeHtmlByThread(out IList<ErrorModel> Errors, IList<PathModel> pathModels)
            {
                lock (lockThis)
                {
                    int count = pathModels.Count / 10;                for (int i = 0; i < 10; i++)    //将任务分发给10个支线程
                    {
                        ThreadEvent[i] = new ManualResetEvent(false);
                        ThreadPool.QueueUserWorkItem(delegate { ToHtml(pathModels.Skip(count * i).Take(count).ToList<PathModel>(), ThreadEvent[(i)]); });
                    }                WaitHandle.WaitAll(ThreadEvent);    //等待所有支线程结束
                }            Errors = errorList;
            }
    还是相同的错误
      

  7.   

    问题解决,我用了另外一个不是很优雅的办法:        List<ErrorModel> errorList = new List<ErrorModel>();
            Thread[] thrads = new Thread[10];        public void MakeHtmlByThread(out IList<ErrorModel> Errors, IList<PathModel> pathModels)
            {
                StartThread(pathModels);
                foreach (Thread t in thrads) t.Join();            Errors = errorList;
            }        private System.Object lockThis = new System.Object();//此对象用于线程安全锁
            public void StartThread(IList<PathModel> pathModels)
            {
                lock (lockThis)
                {
                    int count = pathModels.Count / 10;                for (int i = 0; i < 10; i++)    //将任务分发给10个支线程
                    {
                        thrads[i] = new Thread(ToHtml);
                        thrads[i].Start(pathModels.Skip(count * i).Take(count).ToList<PathModel>());
                    }
                }
            }