使用锁在c#中进行线程化

时间:2016-11-11 19:12:19

标签: c# multithreading locking

我想我在这里错过了一些基础知识而无法解决问题..

以下程序的输出与预期不符。有人可以帮我理解这个问题。

using System;
using System.Threading;

public class Program
{
    private static readonly object _lock = new object();
    public static void Main()
    {
        for (var i = 0; i < 10; i++)
        {
            //Console.WriteLine("Start "+i); 
            System.Threading.Thread thread = new System.Threading.Thread(() => ExecuteInBackground(i));
            thread.IsBackground = true;
            thread.Start();
        }
    }

    private static void ExecuteInBackground(Object obj)
    {
        lock (_lock)
        {
            Console.WriteLine("A "+obj);
            test.ttt(obj);
        }
    }
}


public static class test
{
    public static void ttt(object obj)
    {
        Console.WriteLine("B "+ obj);
    }
}

我希望在输出中看到0到9 ..但实际输出如下..

A 1
B 1
A 1
B 1
A 3
B 3
A 4
B 4
A 5
B 5
A 6
B 6
A 7
B 7
A 8
B 8
A 9
B 9
A 10
B 10

非常感谢任何帮助。

请随意使用https://dotnetfiddle.net/nYfbMU

中的代码

谢谢, 雷迪。

2 个答案:

答案 0 :(得分:4)

改变这个:

for (var i = 0; i < 10; i++)
{
    //Console.WriteLine("Start "+i); 
    System.Threading.Thread thread = new System.Threading.Thread(() => ExecuteInBackground(i));

到此:

for (var i = 0; i < 10; i++)
{
    var temp = i;
    //Console.WriteLine("Start "+i); 
    System.Threading.Thread thread = new System.Threading.Thread(() => ExecuteInBackground(temp));

这是一个关闭问题。见Why is it bad to use an iteration variable in a lambda expression

原始代码没有按预期工作的原因,以及temp变量为什么会这样,是因为() => ExecuteInBackground(i)就像在说&#34;在将来的某个时候,我想要这个新代码线程调用ExecuteInBackground方法,传入任何值进行调用时&#34;。由于循环变量在循环开始时进入范围,并且在循环结束后超出范围,因此i的值在调用Thread的时间和ExecuteInBackground执行时之间发生变化。通过在循环内使用临时变量,循环的每次迭代都超出范围,每个线程对ExecuteInBackground的调用实际上是获得一个不同的变量,每个调用具有不变的值,并且下一次递增i并不会搞砸。

答案 1 :(得分:0)

这对我有用..

using System;
using System.Threading;

public class Program
{
    private static readonly object _lock = new object();
    public static void Main()
    {
        for (var i = 0; i <= 10; i++)
        {
            fn(i);
        }
        Console.ReadLine();
    }

    private static void fn(int i)
    {
        System.Threading.Thread thread = new System.Threading.Thread(() => ExecuteInBackground(i));
        thread.IsBackground = true;
        thread.Start();
    }

    private static void ExecuteInBackground(Object obj)
    {
        lock (_lock)
        {
            Thread.Sleep(500);
            Console.WriteLine("A "+obj);
            test.ttt(obj);
        }
    }
}
public static class test
{
    //private static readonly object _lock = new object();
    public static void ttt(object obj)
    {
        //lock(_lock)
            Console.WriteLine("B "+ obj);
    }
}