锁定所有方法的使用

时间:2015-07-15 15:20:07

标签: c# multithreading

我有一个可以同时从多个线程访问的方法,我想确保只有一个线程可以在任何方法的主体内。

这段代码可以重构为更通用的东西吗? (除了锁定 State 属性?

public class StateManager : IStateManager
{
    private readonly object _lock = new object();
    public Guid? GetInfo1()
    {
        lock (_lock)
        {
            return State.Info1;
        }
    }

    public void SetInfo1(Guid guid)
    {
        lock (_lock)
        {
            State.Info1 = guid;
        }
    }

    public Guid? GetInfo2()
    {
        lock (_lock)
        {
            return State.Info2;
        }
    }

    public void SetInfo2(Guid guid)
    {
        lock (_lock)
        {
            State.Info2 = guid;
        }
    }
}

3 个答案:

答案 0 :(得分:2)

可能是这样的:

private void LockAndExecute(Action action)
{
    lock (_lock)
    {
        action();
    }
}

然后您的方法可能如下所示:

public void DoSomething()
{
    LockAndExecute(() => Console.WriteLine("DoSomething") );
}

public int GetSomething()
{
    int i = 0;
    LockAndExecute(() => i = 1);
    return i;
}

我不确定那真的能拯救你,然而回归的价值确实有点痛苦。

虽然您可以通过添加其他方法来解决这个问题:

private T LockAndExecute<T>(Func<T> function)
{
    lock (_lock)
    {
        return function();
    }
}

所以现在我的GetSomething方法更加清晰:

public int GetSomething()
{
    return LockAndExecute(() => 1 );
}

同样,不确定你在减少打字方面获得了很多,但至少你知道每个电话都锁定了同一个对象

虽然在你需要做的就是锁定的情况下你的收益可能非常小,但我可以想象你有一堆类似的方法:

public void DoSomething()
{
    // check some preconditions
    // maybe do some logging
    try
    {
        // do actual work here
    }
    catch (SomeException e)
    {
        // do some error handling
    }
}

在这种情况下,将所有前提条件检查和错误处理提取到一个地方可能非常有用:

private void CheckExecuteAndHandleErrors(Action action)
{
    // preconditions
    // logging
    try
    {
        action();
    }
    catch (SomeException e)
    {
        // handle errors
    }
}

答案 1 :(得分:0)

使用操作或功能代理。

创建类似

的方法
public T ExecuteMethodThreadSafe<T>(Func<T> MethodToExecute)
    {
        lock (_lock)
        {
            MethodToExecute.Invoke();
        }
    }

并使用它

public T GetInfo2(Guid guid)
        {
            return ExecuteMethodThreadSafe(() => State.Info2);
        }

答案 2 :(得分:0)

我想使用Matt和Abhinav提出的一些想法来总结一下我的观点,以概括这一点,并使其尽可能无缝地实现。

private static readonly object Lock = new object();

public static void ExecuteMethodThreadSafe<T>(this T @object, Action<T> method) {
    lock (Lock) {
        method(@object);
    }
}

public static TResult ExecuteMethodThreadSafe<T, TResult>(this T @object, Func<T, TResult> method) {
    lock (Lock) {
        return method(@object);
    }
}

然后可以按照以下方式进行扩展(如果需要):

private static readonly Random Random = new Random();

public static T GetRandom<T>(Func<Random, T> method) => Random.ExecuteMethodThreadSafe(method);

然后在实施时可能看起来像这样:

var bounds = new Collection<int>();
bounds.ExecuteMethodThreadSafe(list => list.Add(15)); // using the base method
int x = GetRandom(random => random.Next(-10, bounds[0])); // using the extended method
int y = GetRandom(random => random.Next(bounds[0])); // works with any method overload