我有一个可以同时从多个线程访问的方法,我想确保只有一个线程可以在任何方法的主体内。
这段代码可以重构为更通用的东西吗? (除了锁定 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;
}
}
}
答案 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