C# 锁定操作不起作用

C# 锁定操作不起作用,c#,multithreading,locking,C#,Multithreading,Locking,我遇到了一些锁定操作的代码,发现它不起作用。下面是代码的(简化和愚蠢)版本: class Program { static void Main(string[] args) { var settings = new Settings(0); Action<int> threadAction = i => { BusyBody.DoSomething(settings.GetANumber,

我遇到了一些锁定
操作的代码,发现它不起作用。下面是代码的(简化和愚蠢)版本:

class Program
{
    static void Main(string[] args)
    {
        var settings = new Settings(0);
        Action<int> threadAction = i =>
        {
            BusyBody.DoSomething(settings.GetANumber, settings.SetANumber, i);
        };
        ThreadPool.QueueUserWorkItem(delegate { threadAction(1); });
        ThreadPool.QueueUserWorkItem(delegate { threadAction(2); });
        Console.ReadLine();
    }

    class Settings
    {
        int i;

        public Settings(int i)
        {
            this.i = i;
        }

        public int GetANumber() => i;

        public void SetANumber(int i) => this.i = i;
    }

    class BusyBody
    {
        public static void DoSomething(Func<int> getInt, Action<int> setInt, int i)
        {
            lock (setInt)
            {
                Console.WriteLine("Getting int: " + getInt());
                Console.WriteLine("i " + i);
                setInt(i);
                Console.WriteLine("set");
            }
        }
    }
}


取决于哪个线程首先通过
锁。然而,这不是我所看到的。相反,我看到:

Getting int: 0
i 2
Getting int: 0
i 1
set
set
看起来两个线程都进入了
。为什么会发生这种情况?被锁定的
操作
是来自同一对象的同一方法,因此引用不应该相同吗


任何帮助都将不胜感激。谢谢

当您多次将方法强制转换为
操作
时(当您传递
设置.SetANumber
时),这并不意味着您得到相同的
操作
对象。您可以得到多个执行相同操作的
操作
对象

试试这个:

 Action<int> set_action = settings.SetANumber;

 Action<int> threadAction = i =>
 {
     BusyBody.DoSomething(settings.GetANumber, set_action, i);
 };
Action set\u Action=settings.SetANumber;
动作线程动作=i=>
{
爱管闲事的人。做某事(settings.GetANumber,set_action,i);
};

这确保您有一个
操作
对象。

这里的问题是您锁定了两个不同的对象

这一行:

BusyBody.DoSomething(settings.GetANumber, settings.SetANumber, i);
是这个的缩写:

BusyBody.DoSomething(new Func<int>(settings.GetANumber), new Action<int>(settings.SetANumber), i);
BusyBody.DoSomething(新函数(settings.GetANumber)、新操作(settings.SetANumber)、i);
两个
newfunc(…)
newaction(…)
表达式将在每次调用时生成新的委托对象,因此您不会锁定同一个对象实例

如果要共享这些对象,必须创建一次:

...
Func<int> getANumber = settings.GetANumber;
Action<int> setANumber = settings.SetANumber;
Action<int> threadAction = i =>
{
    BusyBody.DoSomething(getANumber, setANumber, i);
};
...
。。。
Func getANumber=settings.getANumber;
Action setANumber=settings.setANumber;
动作线程动作=i=>
{
爱管闲事的人。做某事(getANumber,setANumber,i);
};
...

我认为发生的事情是,您正在创建并锁定引用相同方法的两个不同的
委托
对象。但我不知道如何更正式地表达它。飞碟?“然而这不是我看到的”。你能告诉我们你看到了什么吗?@YacoubMassad用我看到的输出更新了问题。
BusyBody.DoSomething(new Func<int>(settings.GetANumber), new Action<int>(settings.SetANumber), i);
...
Func<int> getANumber = settings.GetANumber;
Action<int> setANumber = settings.SetANumber;
Action<int> threadAction = i =>
{
    BusyBody.DoSomething(getANumber, setANumber, i);
};
...