c#匿名方法的一个注意点

在看Artech的博客时发现他的这篇难道调用ThreadPool.QueueUserWorkItem()的时候,真是必须调用Thread.Sleep(N)吗? 讲到的一个匿名方法造成的问题,在文章后面,有老赵的回复,并且给出了解决方案(查看老赵的“警惕匿名方法造成的变量共享”)。其实不止匿名方法有这个困扰,我们在操作集合的时候,都应该全面考虑到”变量共享“问题。下面就贴一下自己加了几行注释的Artech的源码,从我自己的角度来分析一下:

ExpandedBlockStart.gif 代码
    class  Program
    {
        
static   void  Main( string [] args)
        {
            List
< Action >  actions  =   new  List < Action > ();
            actions.Add(() 
=>  Console.WriteLine( " A1 " ));
            actions.Add(() 
=>  Console.WriteLine( " A2 " ));
            actions.Add(() 
=>  Console.WriteLine( " A3 " ));
            actions.Add(() 
=>  Console.WriteLine( " A4 " ));
            
foreach  (var action  in  actions)
            {
                
// var tmpAction = action;  // 线程执行这个委托方法就输出正常
                
// ThreadPool.QueueUserWorkItem(state => tmpAction(), null);

                ThreadPool.QueueUserWorkItem(state 
=>  action(),  null );
                
// Thread.Sleep(1);  // 不管有没有这一行  都是有问题的
            }
            Console.Read();
        }
    }

 运行后,我们看到的结果和我们理想的相差甚远(加上Thread Sleep(1)那一行运行结果有时也不全是我们想要的结果)。
其实我们完全可以这样理解:在foreach循环的时候,action是一个委托方法引用,是引用类型,线程执行的时候,都将执行action变量所在的同一引用地址上的委托方法。而我们将action赋值给一个中间变量tmpAction后,每循环一次,就相当于在内存上重新分配了一段空间,然后线程执行一个新引用地址上的委托方法,这就避免了老赵所说的“匿名方法造成的变量共享”。
ps:我在早前一篇博客里讲到匿名方法的“一个需要注意的地方”的时候也提到了这一点,不知各位是否赞同。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值