Task并发,帮忙看一下

Aries_0219 2015-05-17 06:45:08
for (int i = 0; i < 10; i++)
{

new TaskFactory().StartNew(() =>
{
Console.WriteLine(i);

});
}

控制台里面运行,为何打印出来所有都是10?


for (int i = 0; i < 10; i++)
{

Thread.Sleep(100);
new TaskFactory().StartNew(() =>
{
Console.WriteLine(i);

});
}

改成这样就可以连续打印了?

两个区别是什么?
...全文
394 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
gengchenhui 2015-05-20
  • 打赏
  • 举报
回复
楼主只需要看sp1234一个人的回复就行了。。。 其他像说“循环完了,还没new出来”那只是表象问题,真正的原因并不是这个,这也是我当初在看“闭包”这个概念的时候了解到的一点。。。
  • 打赏
  • 举报
回复
引用 4 楼 starfd 的回复:
没有sleep的时候,for循环执行的太快了,快到task都还没new出来
我不建议这样解释这个问题。这会让初学者误解,以为有经验的人把sleep真的看作是一种“解决问题”的设计方法,从而继续使用和纠结于sleep代码。
  • 打赏
  • 举报
回复
正常的程序,1毫秒不到就能给出结果。而你写的sleep,则需要1000毫秒。 实际上这也就是因为for循环的上限是10。如果是100000,你的sleep(100)还不够呢,还要“延长”。成了一个恶性循环。 原本要并发执行的东西,而你改为“每一个操作都无限期地等待很久很久时间,然后才敢进行下一个操作”,这就非常荒唐了。有的人写个通讯程序,数据混乱,于是就也是写个sleep.......凡是在多线程并发操作时程序混乱的人如果都去写sleep然后说“这样就可以解决”了,那么将是多么可怖事情啊,原本用10毫秒的程序它现在是50秒钟才执行完,不但是慢了50000倍速度,而且这个sleep间隔还是一个“未知数”需要不断手工猜测修改。 写sleep这个做法,不用考虑什么“区别”,它根本就不是一个正常的思维方式,它根本就推迟到无限长时间之后才启动下一个任务了,还谈什么“task并发”呢?
lee576 2015-05-18
  • 打赏
  • 举报
回复
TaskFactory().StartNew( 这里面是一个闭包,5楼都已经说了,lambda表达式使用循环里面的变量,在循环体里面要重新定义一个变量赋值后再使用
  • 打赏
  • 举报
回复

2013运行的结果……
华芸智森 2015-05-18
  • 打赏
  • 举报
回复
sleep用的还是蛮多的,学习下 ------------------------------ 是用得挺多的,尤其是以前的方式写的多线程.需要同步最后的结果.一般都要用到 sleep 在主程序后自旋.
  • 打赏
  • 举报
回复
楼上说的对,这是闭包的经典问题。C# 5.0以上版本做了修改,楼主的程序可以给出预想的结果,否则就要用2楼的方法。不过,应该意识到这个闭包造成的问题,这样在其他语言如javascript编程时就可避免出现同样的问题。
慧眼识狗熊 2015-05-18
  • 打赏
  • 举报
回复
sleep用的还是蛮多的,学习下
chenzhe014 2015-05-18
  • 打赏
  • 举报
回复
在c#4或更早版本的编译器时会出现这种结果。 在for(foreach)循环中使用闭包时,所创建的函数是在调用时、而不是在迭代时获得变量i的值。编译器会从foreach语句创建一个while循环,在while循环外部定义循环变量,在每次迭代中重用这个变量。因此,在循环结束时,该变量的值就是最后一次迭代时的值。 要想在c#4中连续打印,必须使用一个局部变量,并将这个局部变量传入Lambda表达式。这个每次迭代时就将保留一个不同的值。
江南小鱼 2015-05-18
  • 打赏
  • 举报
回复
调试看下反汇编,可能就知道怎么回事了。
john_QQ:2335298917 2015-05-18
  • 打赏
  • 举报
回复
学习了,涨了知识了
qldsrx 2015-05-18
  • 打赏
  • 举报
回复
反编译下看看就知道原因了
  • 打赏
  • 举报
回复
在多线程处理过程中,由于程序的数据段是整个进程共享的,如果你的线程操作访问了共享的数据,必定会存在访问冲突的问题。 常见的做法就是两种:对于简单的参数,进行复制,然后使用私有的(非共享的)对象;对于复杂且需要共享访问的对象,个别代码必须设置一个”临界区“——使用加锁来阻塞其多线程访问。 程序运行的目的当然是又快又准确地完成操作。既不能无限地牺牲内存,也不能无限制地拖慢运行时间。
threenewbee 2015-05-17
  • 打赏
  • 举报
回复
这和并发没有关系,和lambda闭包变量有关。估计你用的是VS2010 建议你在VS2012或更新版本再试。
  • 打赏
  • 举报
回复
没有sleep的时候,for循环执行的太快了,快到task都还没new出来
  • 打赏
  • 举报
回复
不要使用 Sleep。使用Sleep来“解决”并发控制问题的做法,其实都是“瞎猫碰上死耗子”的结果,只是“自以为”解决了问题。 换个角度看,如果你不得不Sleep,你应该知道这种方式一定是“弱爆了”。使用计算机的目的本来就是为了利用它的处理能力而尽快得到计算结果,一个编程的人怎么还能能去写出Sleep这种代码呢?!
  • 打赏
  • 举报
回复
for (int i = 0; i < 10; i++)
{
    var k = i;
    new TaskFactory().StartNew(() =>
    {
        Console.WriteLine(k);

    });
}
pengxiaoshuang0 2015-05-17
  • 打赏
  • 举报
回复
在研究一下啊

110,545

社区成员

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

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

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