【发布时间】:2019-05-20 17:54:43
【问题描述】:
我正在尝试提供一种锁定全局资源的解决方案,以强制锁定访问并且可用于同步或异步操作。
我创建了一个通用类State:
public class State<T>
{
public class LockedState : IDisposable {
public LockedState(State<T> state) { this.state = state; Monitor.Enter(this.state.theLock); } // would be great if this could be private
public void Dispose() => Monitor.Exit(this.state.theLock);
public ref T Val { get { return ref state.t; } }
readonly State<T> state;
};
public State() { }
public State(T t) { this.t = t; }
public LockedState Locked { get { return new LockedState(this); } }
readonly object theLock = new object();
T t;
}
这里的想法是我可以在 Program 类中拥有一个全局“存储”:
public class Program {
static public readonly State<ImmutableList<int>> TheList = new State<ImmutableList<int>>(ImmutableList<int>.Empty);
static public readonly State<SomeType> SomeType = new State<SomeType>(SomeType());
}
然后唯一访问状态的方法是像这样获取锁:
using (var lTheList = Program.TheList.Locked) {
lTheList.Val = lTheList.Val.Add(5));
}
在我的情况下,它比普通锁效果更好,因为它在获取/设置之前强制锁定(你不能忘记锁定)
(旁注这是一个好策略吗?)
问题是我不能在异步代码中使用上述内容:
using (var someType = Program.SomeType.Lock()) {
var x = await someType.Val.SomeAsyncOp();
}
我得到一个例外:Object synchronization method was called from an unsynchronized block of code
我发现这篇帖子 How to protect resources that may be used in a multi-threaded or async environment? 有一个 AsyncLock 类但是我不明白如何将像 AsyncLock 这样的类放入我的 StateLock 类中......
State.Lock() 能否返回可用于同步和异步调用者的锁定状态?这真的是我要找的!
如果不是,我最好的前进方式是什么?使用SemaphoreSlim 并拥有State.Lock() 和State.AsyncLock() ?
谢谢!
【问题讨论】:
-
为什么你不使用
lock-statement?见docs.microsoft.com/en-us/dotnet/csharp/language-reference/… -
不完全确定 using 语句(因此 try/finally 阻止它)是否阻止了这一点,但我认为问题如下:在等待之前执行代码的线程(获取锁)可以是不同的线程,然后线程在等待(释放锁)之后执行代码。由于 Monitor 是可重入的,我认为它会跟踪哪个线程拥有锁,我可以想象当另一个线程然后拥有的线程尝试释放 Monitor 时会引发此错误。
-
knoop 是的,这就是问题所在......我怎样才能最好地解决它?
-
抱歉,您还不清楚为什么会发生此错误。正如您链接信号量的线程中提到的那样,这似乎是要走的路:stackoverflow.com/questions/11001760/…。
标签: c# .net async-await c#-7.0