多线程的问题求救啊

风吹腚腚凉 2016-10-14 11:24:39
List<int> dint=new List<int>();

for (int i = 0; i < 100; i++)
{
dint.Add(i);
}
//new b().test(i)
Parallel.ForEach(dint, item =>
{
ListString.Add(item.ToString());
Thread.Sleep(100);

}
);
while (ListString.Count < 99)
{
Thread.Sleep(300);
}
string ddddd = "";
foreach (string item in ListString)
{
ddddd += item + ",";
}
为啥死循环?ListString.Count < 99
...全文
606 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
风吹腚腚凉 2016-10-17
  • 打赏
  • 举报
回复
引用 17 楼 zanfeng 的回复:
并行应该不这样用的吧。
是的,我只是做测试而已。
足球中国 2016-10-15
  • 打赏
  • 举报
回复
并行应该不这样用的吧。
足球中国 2016-10-15
  • 打赏
  • 举报
回复
vs2010直接报地址越界了。出错了。
风吹腚腚凉 2016-10-14
  • 打赏
  • 举报
回复
引用 3 楼 starfd 的回复:
List<int> dint = new List<int>();
List<string> ListString = new List<string>();

for (int i = 0; i < 100; i++)
{
    dint.Add(i);
}
//new b().test(i)
Parallel.ForEach(dint, item =>
{
    ListString.Add(item.ToString());
    Thread.Sleep(100);

}
    );
while (ListString.Count < 99)
{
    Thread.Sleep(300);
}
string ddddd = "";
foreach (string item in ListString)
{
    ddddd += item + ",";
}
Console.WriteLine(ddddd);
试了下没问题啊
100改成1000试试
Poopaye 2016-10-14
  • 打赏
  • 举报
回复
int[] x = new int[100000];
int y = 0;
var result = Parallel.ForEach(x, item => { y++; });
if(result.IsCompleted)
    Console.WriteLine(y);
像这样,10次里面基本
Poopaye 2016-10-14
  • 打赏
  • 举报
回复
Parallel是并行,但是不保证里面的ListString.Add也是线程安全的啊
  • 打赏
  • 举报
回复
List<int> dint = new List<int>();
List<string> ListString = new List<string>();

for (int i = 0; i < 100; i++)
{
    dint.Add(i);
}
//new b().test(i)
Parallel.ForEach(dint, item =>
{
    ListString.Add(item.ToString());
    Thread.Sleep(100);

}
    );
while (ListString.Count < 99)
{
    Thread.Sleep(300);
}
string ddddd = "";
foreach (string item in ListString)
{
    ddddd += item + ",";
}
Console.WriteLine(ddddd);
试了下没问题啊
xuzuning 2016-10-14
  • 打赏
  • 举报
回复
访问公共资源,应该加锁吧? lock (ListString) ???
风吹腚腚凉 2016-10-14
  • 打赏
  • 举报
回复
去掉 Thread.Sleep(100);就好了为啥? BUG?
qbilbo 2016-10-14
  • 打赏
  • 举报
回复
引用 13 楼 wjfwd2010 的回复:
我用的VS2013麻痹的跟版本还有关系么?不可能吧?如果是那微软就太傻比了,我很纳闷, 据说list是线程安全的,线程安全表示执行过程中不会出异常,但是是不是,不表示说这个对象插入的数据就一定正确? 你用VS2013试试
MSDN的原话是:此类型的公共静态(在 Visual Basic 中为 Shared)成员是线程安全的。但不能保证任何实例成员是线程安全的。 https://msdn.microsoft.com/zh-cn/library/6sh2ey19(v=vs.100).aspx
stherix 2016-10-14
  • 打赏
  • 举报
回复
引用 13 楼 wjfwd2010 的回复:
我用的VS2013麻痹的跟版本还有关系么?不可能吧?如果是那微软就太傻比了,我很纳闷, 据说list是线程安全的,线程安全表示执行过程中不会出异常,但是是不是,不表示说这个对象插入的数据就一定正确? 你用VS2013试试
list不是线程安全的 所谓的非线程安全 不一定100%就会出错 而是随机性的 所以尽量自己同步 而不能靠运气跑过去
风吹腚腚凉 2016-10-14
  • 打赏
  • 举报
回复
我用的VS2013麻痹的跟版本还有关系么?不可能吧?如果是那微软就太傻比了,我很纳闷, 据说list是线程安全的,线程安全表示执行过程中不会出异常,但是是不是,不表示说这个对象插入的数据就一定正确? 你用VS2013试试
维秀斯丢丢 2016-10-14
  • 打赏
  • 举报
回复
大家回答,麻烦先运行一下程序先。 没什么错误。也没有死循环。
编程有钱人了 2016-10-14
  • 打赏
  • 举报
回复
核心问题就是 List 不是线程安全的
圣殿骑士18 2016-10-14
  • 打赏
  • 举报
回复
ConcurrentBag,好二的名字呀
EnForGrass 2016-10-14
  • 打赏
  • 举报
回复
可以用ThreadPool.QueueUserWorkItem 方法 (WaitCallback)将方法排入队列以便执行,WaitCallback,表示要执行的方法。如果将方法成功排入队列,则为 true;否则为 false。

   System.Threading.ThreadPool.QueueUserWorkItem(w =>
            {
                Parallel.ForEach(dint, item =>
            {
                ListString.Add(item.ToString());
            });

            });
qbilbo 2016-10-14
  • 打赏
  • 举报
回复
根本原因是:List<T>的Add方法不是线程安全的。 当把sleep去掉能成功是因为这个运算耗时太短,并没有用多个线程处理,或是运气较好。把100改成100000什么的,可能就可以看出问题了。 解决方法: 用:System.Collections.Concurrent.ConcurrentBag代替:System.Collections.Generic.List。ConcurrentBag中的方法是线程安全的。或象xuzuning说的那样,给 :ListString.Add(item.ToString());这句加锁。
List<int> dint = new List<int>();
            List<string> ListString = new List<string>();
            //ConcurrentBag<string> ListString = new ConcurrentBag<string>();
            for (int i = 0; i < 100000; i++)
            {
                dint.Add(i);
            }
            //new b().test(i)
            Parallel.ForEach(dint, item =>
            {
                ListString.Add(item.ToString());
                //Thread.Sleep(10);
            }
                );
            Console.Write("已经添加了:{0}条记录。", ListString.Count);
            Console.ReadKey();
            while (ListString.Count < 999999)
            {
                Thread.Sleep(300);
            }
            string ddddd = "";
            foreach (string item in ListString)
            {
                ddddd += item + ",";
            }
            Console.WriteLine(ddddd);
切换一下注释掉的ListString的定义就可以看出效果。
xuzuning 2016-10-14
  • 打赏
  • 举报
回复
Parallel.ForEach(dint, item => { ListString.Add(item.ToString()); Thread.Sleep(100); }); 多次运行 ListString.Count 均小于 100 去掉 Thread.Sleep(100); 或加 lock (ListString) 或加 Console.WriteLine(item); 多次运行 ListString.Count 均等于 100

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧