提供有关 .NET 3.5 中状态信息的锁定机制
我试图找到一种方法来提供对资源的独占访问,同时提供有关锁状态(_isWorking)的信息以供其他类读取。
这是我到目前为止所想到的:
private int _isWorking = 0;
public bool IsWorking
{
get { return Interlocked.CompareExchange(ref _isWorking, 0, 0) == 1; }
}
public void LaunchProcess()
{
if (Interlocked.CompareExchange(ref _isWorking, 1, 0) == 0)
{
try
{
DoExpansiveProcess();
}
finally
{
Interlocked.Exchange(ref _isWorking, 0);
}
}
}
public void DoExpansiveProcess()
{
Thread.Sleep(30000);
}
它并不完全像锁一样工作,因为第二个线程在看到一个线程已经在运行该进程时,将离开该方法而不执行任何操作。
这是执行此操作的正确方法吗?还是有更适合此目的的 C# 3.5 结构?
如何实现“真正的”锁定场景,其中第二个线程在第一个线程完成后仍会执行该方法,同时提供有关状态的信息?
I'm trying to find a way to provide exclusive access to a resource, while at the same time providing information about the state of the lock (_isWorking) for other classes to read.
Here's what I have come up with so far :
private int _isWorking = 0;
public bool IsWorking
{
get { return Interlocked.CompareExchange(ref _isWorking, 0, 0) == 1; }
}
public void LaunchProcess()
{
if (Interlocked.CompareExchange(ref _isWorking, 1, 0) == 0)
{
try
{
DoExpansiveProcess();
}
finally
{
Interlocked.Exchange(ref _isWorking, 0);
}
}
}
public void DoExpansiveProcess()
{
Thread.Sleep(30000);
}
It does not work exactly as a lock since the second thread, upon seeing that a thread is already running the process, will just leave the method and do nothing.
Is it the correct way to do this or are there any C# 3.5 structure more adapted for the purpose?
And how to implement a 'real' lock scenario, where the second thread would still execute the method after the first one finishes, while providing information about the state?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
假设我正确理解你的问题,那么我认为你所追求的是超时值为 0 的
Monitor.TryEnter
方法。它将尝试获取锁,但超时值为 0 时它会总是立即返回,并返回指示是否实际获取锁的值。这里的含义是,如果锁没有被获取,那么就假设它已经被其他人获取了。问题是,如果返回 true,那么您必须立即通过调用 Monitor.Exit 来释放它。也许这将是一个更好的解决方案:
Assuming that I understand your question correctly then I think what you are after is the
Monitor.TryEnter
method with a timeout value of 0. It will attempt to acquire the lock, but with a timeout of 0 it will always return immediately with value indicating whether the lock was actually acquired. The implication here is that if the lock was not acquired then it is assumed that it is already acquired by someone else. The problem is that if returnstrue
then you would have to immediately release it with a call toMonitor.Exit
.Perhaps this would be a better solution:
System.Threading.ManualResetEvent
可能可以在这里提供帮助。只需对其执行 WaitOne() 即可。如果它被使用,那么它将返回错误。如果未使用,则可以使用。WaitOne() 重载之一需要等待一段时间(以毫秒为单位)。如果您使用 WaitOne(0),则等待将以非阻塞方式立即返回。
您应该对 .Net 提供的同步原语进行一些研究:
System.Threading.ManualResetEvent
might be able to help here. Just do a WaitOne() against it. If it's being used then it will come back as false. If it isn't in use it is available.One of the WaitOne() overloads takes a time in milliseconds to wait. If you use WaitOne(0) then the wait will return immediately in a non blocking way.
You should do some research into the synchronisation primitives that .Net offers:
我认为您的方法通常应该是正确的,并且肯定比使用 ManualResetEvent (如果它完全相关)快得多 - 因为 ManualResetEvent 包装了底层的非托管原语。
然而,为了使这种方法安全,_isWorking 必须是私有的。
I think your approach should in general be correct and will definitely be much faster than using a ManualResetEvent (if its at all relevant) - because ManualResetEvent wraps underlying unmanaged primitive.
To make this approach safe however, _isWorking has to be private.