本帖最后由 backslash 于 2012-07-21 22:47:42 编辑

解决方案 »

  1.   

    图没显示全,完整原图地址:
    http://img.my.csdn.net/uploads/201207/21/1342882373_3204.jpg
      

  2.   

    第一个线程还没有执行完毕,salesman的引用已经更改为第二个对象了,所以第一个线程加的结果就移到第二个里面了。解决办法
    定义全局变量
    private object lockObj=new object();for(int i=0;i<salesman.Length;i++)
    {
        SalesmanModel data;
        lock(this.lockObj)
        {
             data=salesman[i];
        }
        for(int j=0;i<2000;j++)
        {
             data.SalesVolume++;
        }
    }
    手写的不一定正确,lz看下行不行。
      

  3.   

    忘记加多线程了。
    private object lockObj=new object();for(int i=0;i<salesman.Length;i++)
    {
      SalesmanModel data;
      lock(this.lockObj)
      {
          data=salesman[i];
      }
      new Thread(()=>
      {
          for(int j=0;i<2000;j++)
         {
            data.SalesVolume++;
         }
      }).Start();
    }
      

  4.   

    当你执行foreach的同时,线程也在并行执行。你的线程因为共用了salesman变量,结果它们内部就张冠李戴了,有不止一个线程其实都针对同一个对象进行累加。
      

  5.   

    请使用ParameterizedThreadStart,并在Start时将循环变量传入
      

  6.   

    不要随便加锁。加锁就等于你去用异步线程的语法去模拟同步阻塞,是很糟糕的设计,而且你的程序反而比单线程运行的还慢。线程应该:foreach(var s in salesmen)
    {
        var c=s;
        然后在线程中引用c而不是s!
    }需要临时复制你的salesman变量值。
      

  7.   

    嗯sorry,上面“并在Start时将循环变量传入”是可以的。
      

  8.   

    晕!你要把值赋给c,因为c才是你真正的saleman,才不会张冠李戴。怪不得你的结果会乱,原来这个道理过了要这么长时间还不能想通。你自己实际测试一下。
      

  9.   

     foreach (var salesman in salesmen)
                {
                    new Thread(new ParameterizedThreadStart(param =>
                    {
                        for (int i = 0; i < 2000; i++)
                        {
                            (param as SalesmanModel).SalesVolume += 1;
                        }                    _countdown.Signal();                })).Start(salesman);
                }
      

  10.   

    噢,明白了。之前是共用了salesman变量,现在是用c把对象提出来。
      

  11.   

    foreach(var s in salesmen)
    {
        var c=s;
        然后在线程中引用c而不是s!
    }
    var c=s;应该是创建一个c引用地址到s指向的堆中,s的引用地址改变,c应该是不会改变的,但这种写法结果还是和lz的一样,有些不解了。多线程我现在的理解是可以减少代码的执行的等待时间,
    虽然在lock的地方会阻塞,但是在没有lock地方的代码会得到异步执行,提高了效率多线程加锁可以理解为多个人做一件事情,但是有一个管理员(lock)分配任务,那个人分配完,就可以去做事情了,而不需要像接力棒那样,一个人做完一件事情另一个人才能够再做事,这样效率会得到提高而且你的程序反而比单线程运行的还慢。
    出现这种情况,是线程过多,执行的方法花费时间长,造成过多的线程等待分配任务,影响了效率,个人觉得怎么都会比单线程快,除非出现线程堵塞。
    附上一个刚刚写的测试,楼主可以照着改一下就可以在你项目中用了
    public class Test
        {
            public int volume { set; get; }        public string name { set; get; }
        }
        class Program
        {
            private static object lockObj = new object();        static void Main(string[] args)
            {
                List<Test> list = new List<Test>();
                for (int i = 0; i < 5; i++)
                {
                    Test data = new Test();
                    data.name = i.ToString();
                    list.Add(data);
                }            foreach (Test item in list)
                {
                Test data=item;
                //for (int i = 0; i < list.Count; i++)
                //{
                //    Test data;
                    //lock (lockObj)
                    //{
                    //    data = list[i];
                    //}
                    new Thread(() =>
                    {
                        for (int j = 0; j < 2000; j++)
                        {
                            data.volume++;
                        }
                    }).Start();
                }
                int total = 0;
                foreach (Test item in list)
                {
                    total += item.volume;
                    Console.WriteLine(item.name + "--" + item.volume);
                }
                Console.WriteLine("总数:" + total.ToString());
                return;
            }
      

  12.   

    这种写法不需要加锁
    for (int i = 0; i < list.Count; i++)
                {
                    Test data=list[i];
                    //lock (lockObj)
                    //{
                    //    data = list[i];
                    //}
                    new Thread(() =>
                    {
                        for (int j = 0; j < 2000; j++)
                        {
                            data.volume++;
                        }
                    }).Start();
                }
      

  13.   

    嗯,slyzly的写法跟sp1234意思是一样的。
    不过我觉得iyomumx说得使用ParameterizedThreadStart是略微合适的。