ASP.NET网站制作之制止在多线程的回调匿名函数中毛病地利用部分变量仓酷云
简单的说:.net只有微软一家在做的,微软也不允许别人跟他做相同的工具,所以他就把需要的工具全部封装在.net的平台上了;而net网页编程是公开了。成绩:因为在多线程中利用了匿名函数外的部分变量而招致的Bug实行代码
staticvoidMain(string[]args)
{
for(inti=0;i<10;i++)
{
Threadt=newThread(delegate()
{
Thread.Sleep(newRandom().Next(1,10000));
Console.Write(i+",");
});
t.Start();
}
}
将失掉输入:10,10,10,10,10,10,10,10,10,10,
而不是我们希冀的相似于:3,5,6,1,0,7,9,8,4,2,如许的输入。这是为何呢?(在实践项目中呈现这个Bug的代码请参考)
剖析:利用Reflector检察编译以后的代码
上面是编译前后的代码对照。(利用Reflector的详细办法请参考,这里仅展示了局)
<br>
能够发明,i关于匿名办法来讲算得上是“全局”变量,假如在线程处置i之前,i的值就被改动了的话,就会呈现我们不但愿呈现的了局。
办理办法1:利用更小局限的部分变量
我们做一个小小的变动,在for轮回内里界说一个变量j,让匿名函数只会见这个j
<br>
以是运转程序,可失掉准确的输入:3,5,6,1,0,7,9,8,4,2,
由此,我们能够做出一个假定:编译器会在声明匿名函数所利用的部分变量的中央声明AutoGenClass的实例。那末,能够推出另外一个结论:假如匿名函数内里利用了成员变量,那末ThreadStart对象也会酿成成员变量,有乐趣的话能够本人用Reflector看一下。
这个办法固然能无效办理成绩,但有一个弱点:声明一时变量的企图不分明。为了不哪天有个非常热情又不明就里的程序员以为“变量j基本和i一样嘛”而把j给移除,我激烈倡议在j的前面加一个正文:“这里声明一个一时变量j是有深意的,谁敢动它老子跟谁玩命!!”。为制止这个弱点,可思索利用上面的办理办法。
办理办法2:在匿名函数中只利用它的参数
<br>
此次匿名函数压根就没利用“全局”变量,以是一样可失掉准确的了局:9,7,0,5,3,8,1,6,4,2,
假如必要利用线程池,代码迥然不同:
staticvoidMain(string[]args)
{
for(inti=0;i<10;i++)
{
ThreadPool.QueueUserWorkItem(delegate(objectarg)
{
Thread.Sleep(newRandom().Next(1,1000));
Console.Write(arg+",");
},i);
}
Thread.Sleep(10000);
}
既然在匿名函数内里利用可(在函数外)被变动的部分变量是云云伤害,我们是不是应当往微软总部门前请愿,请求在匿名函数里只能利用被声明为readonly的部分变量呢?就这么定了!机票钱老赵出,如今报名……
偶还没YY够,Boss就喜洋洋的对我吼道,这TMD是怎样回事?为何你的程序输入的了局是无序的?即刻给我改成输入0,1,2,3,4,5,6,7,8,9,!
但是我们用的多线程呀,怎样能包管各个线程按按次获得数据呢?这类时分,能利用部分变量就便利多了。
办理办法3:利用泛型Queue传送数据
代码以下:
staticvoidMain(string[]args)
{
Queue<int>q=newQueue<int>();
for(inti=0;i<10;i++)
{
q.Enqueue(i);
Threadt=newThread(delegate()
{
Thread.Sleep(newRandom().Next(1,10000));
lock(q)
{
if(q.Count>0)
Console.WriteLine(Thread.CurrentThread.Name+":do"+q.Dequeue());
}
});
t.Name="线程"+i;
t.Start();
}
}输入:
线程2:do0
线程1:do1
线程7:do2
线程9:do3
线程3:do4
线程5:do5
线程6:do6
线程8:do7
线程0:do8
线程4:do9
请按恣意键持续...
利用了线程同步以后,线程们排着队往Queue里取数据,然后实行,在效力上就表现不出多线程的上风了。不外,假如换成用线程池使用背景余暇线程仍是成心义的。
伶俐的你必定想到了,泛型Queue一样能够经由过程参数传送出来。
staticvoidMain(string[]args)
{
Queue<int>q=newQueue<int>();
for(inti=0;i<10;i++)
{
q.Enqueue(i);
Threadt=newThread(delegate(objectarg)
{
Thread.Sleep(newRandom().Next(1,10000));
Queue<int>qq=argasQueue<int>;
lock(qq)
{
if(qq.Count>0)
Console.WriteLine(Thread.CurrentThread.Name+":do"+qq.Dequeue());
}
});
t.Name="线程"+i;
t.Start(q);
}
}
结论
既然.net供应了由线程向匿名函数传送参数值的功效,你想要定下一条“多线程回调的匿名函数只同意利用它的参数,克制利用函数外的变量”的礼貌是能够了解的。固然,因为参数只能有一个,以是必要传送多个数值的时分就必需提早机关一个数组或Struct,这几仍是有些方便。让我们往微软门前游行,请求为Thread.Start()供应一个可变参数的重载吧,机票钱老赵出……
参考文献
JeffreyZhao,小心匿名办法酿成的变量共享。cnblogs,2009.
菩提树下的杨过,使用Reflector把"闭包"看分明。cnblogs,2009.
overred,《你不经常使用的c#之三》:Action之怪状。cnblogs,2009.
本文来自:http://www.ckuyun.com/1-2-3/archive/2009/03/16/thread-anonymous-method.html
以前学了大概半年时间的asp(没有机会做大系统,最多是自己对公司系统做些调整和修改还有一些小程序)。应该说开始接触asp.net是今年元月5号的事。现在很想把公司的系统重新用.net来架构,却不知道如何下手。 主流网站开发语言之PHP:PHP的全名非常有趣,它是一个巢状的缩写名称——“PHP:HypertextPreprocessor”,打开缩写还是缩写。PHP是一种HTML内嵌式的语言(就像上面讲的ASP那样)。而PHP独特的语法混合了C,Java,Perl以及PHP式的新语法。它可以比CGI或者Perl更快速地执行动态网页。 主流网站开发语言之ASP:ASP是微软(Microsoft)所开发的一种后台脚本语言,它的语法和VisualBASIC类似,可以像SSI(ServerSideInclude)那样把后台脚本代码内嵌到HTML页面中。虽然ASP简单易用,但是它自身存在着许多缺陷,最重要的就是安全性问题。 同时也感谢博客园给我们这个平台,也感谢博客园的编辑们做成专题引来这么多高人指点。 使用普通的文本编辑器编写,如记事本就可以完成。由脚本在服务器上而不是客户端运行,ASP所使用的脚本语言都在服务端上运行,用户端的浏览器不需要提供任何别的支持,这样大提高了用户与服务器之间的交互的速度。 ASP.Net和ASP的最大区别在于编程思维的转换,而不仅仅在于功能的增强。ASP使用VBS/JS这样的脚本语言混合html来编程,而那些脚本语言属于弱类型、面向结构的编程语言,而非面向对象。 众所周知,Windows以易用而出名,也因此占据不少的服务器市场。 那么,ASP.Net有哪些改进呢? 主流网站开发语言之PHP:PHP的全名非常有趣,它是一个巢状的缩写名称——“PHP:HypertextPreprocessor”,打开缩写还是缩写。PHP是一种HTML内嵌式的语言(就像上面讲的ASP那样)。而PHP独特的语法混合了C,Java,Perl以及PHP式的新语法。它可以比CGI或者Perl更快速地执行动态网页。 网页从开始简单的hmtl到复杂的服务语言,走过了10多个年头,各种技术层出不穷,单个的主流技术也在不断翻新的版本,现在分析下各种语言的区别、优势、劣势、开发注意事项! 主流网站开发语言之CGI:CGI就是公共网关接口(CommonGatewayInterface)的缩写。它是最早被用来建立动态网站的后台技术。这种技术可以使用各种语言来编写后台程序,例如C,C++,Java,Pascal等。 主流网站开发语言之ASP:ASP是微软(Microsoft)所开发的一种后台脚本语言,它的语法和VisualBASIC类似,可以像SSI(ServerSideInclude)那样把后台脚本代码内嵌到HTML页面中。虽然ASP简单易用,但是它自身存在着许多缺陷,最重要的就是安全性问题。 主流网站开发语言之PHP:PHP的全名非常有趣,它是一个巢状的缩写名称——“PHP:HypertextPreprocessor”,打开缩写还是缩写。PHP是一种HTML内嵌式的语言(就像上面讲的ASP那样)。而PHP独特的语法混合了C,Java,Perl以及PHP式的新语法。它可以比CGI或者Perl更快速地执行动态网页。 同时也感谢博客园给我们这个平台,也感谢博客园的编辑们做成专题引来这么多高人指点。 在asp.net虚拟主机的服务提供商中,目前首推的是CNNIC的其中一家域名注册机构---时代互联(www.now.net.cn),他们早在2001年微软刚推出Asp.net时就推出了对应的Asp.net虚拟主机了,经笔者的使用测试,他提供的Asp.net性能非常的稳定,版本也会定期的更新,目前他的 同时也感谢博客园给我们这个平台,也感谢博客园的编辑们做成专题引来这么多高人指点。
页:
[1]