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


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

    代码
       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:我在早前一篇博客里讲到匿名方法的“一个需要注意的地方”的时候也提到了这一点,不知各位是否赞同。


    作者:Jeff Wong
    出处:http://jeffwongishandsome.cnblogs.com/
    本文版权归作者和博客园共有,欢迎围观转载。转载时请您务必在文章明显位置给出原文链接,谢谢您的合作。

  • 相关阅读:
    sublime there are no packages for installation
    linux 安装php扩展mbstring
    生成器表达式和列表推导式
    send()和next()
    迭代器生成器
    装饰器
    函数随笔
    Django进阶
    数据结构与算法入门
    MySQL必会
  • 原文地址:https://www.cnblogs.com/jeffwongishandsome/p/1559998.html
Copyright © 2020-2023  润新知