多线程BUG捕捉之:匿名函数带来的问题

30 篇文章 1 订阅
13 篇文章 0 订阅

     最近有一个隐藏的BUG,是因为使用匿名函数导致的。

     要重现该BUG,可以先查看如下两个程序。

     第一个:

    class Program
    {
        static void Main(string[] args)
        {
            for (int i = 0; i < 10; i++)
            {
                DisplayInt(i);
            }
            Console.Read();
        }

        private static void DisplayInt(int i)
        {
            MethodInvoker mi = new MethodInvoker(delegate()
            {
                Thread.Sleep(1000);
                Console.Write(i);
            });
            mi.BeginInvoke(null, null);
        }
    }

    输出为:0 1 2 …… 9

   

    第二个程序,采用匿名函数的方式来完成相同的功能:

    class Program
    {
        static void Main(string[] args)
        {
            for (int i = 0; i < 10; i++)
            {
                MethodInvoker mi = new MethodInvoker(delegate()
                {
                 Thread.Sleep(1000);
                 Console.Write(i);
                });
                mi.BeginInvoke(null, null);
            }
            Console.Read();
        }

    }

    结果发现,事情并不是我们想象的那样,而是

    输出为:10 10 10 …… 10

   

    分析其原因,在第二个程序中,虽然匿名函数和第一个程序中的DisplayInt完成的是一样的功能。但是这个功能本身是要新起一个线程来执行打印i。而i这个参数,是由主线程传入进去的。那么,可以理解为,在第二个程序中,主线程中的FOR循环已经执行完毕的时候,FOR循环所起的10个工作线程,还没有启动,当它们由.NET运行时环境自行决定启动的时候(当然,这个事件会很短),FOR循环中的i已经变成10,所以,第二个程序产生了上面的结果。

    当然,我想,这个结果应该也不唯一,这完全取决于匿名函数中的线程执行的时候FOR循环是否已经执行完毕了。

    回过头来,考虑第一段代码,因为不是使用的匿名函数,所以内存地址中,保留了一个i的副本,故程序执行正确。


   

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值