我正在尝试找到一种方法来提供对资源的独占访问,同时提供有关锁定状态的信息(_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结构?
如何实现一个“真正的”锁定场景,第二个线程在第一个线程结束后仍会执行该方法,同时提供有关状态的信息?
答案 0 :(得分:1)
假设我正确理解了你的问题,那么我认为你所追求的是Monitor.TryEnter
方法,其超时值为0.它会尝试获取锁定,但是如果超时为0,它将始终返回立即获得指示锁是否实际获得的值。这里的含义是,如果没有获得锁定,则认为它已被其他人获取。问题是,如果返回true
,那么您必须立即通过调用Monitor.Exit
来释放它。
也许这是一个更好的解决方案:
public class Worker
{
private Object m_LockObject = new Object();
private volatile bool m_IsWorking = false;
public bool IsWorking
{
get { return m_IsWorking; }
}
public void LaunchProcess()
{
lock (m_LockObject)
{
m_IsWorking = true;
DoExpansiveProcess();
m_IsWorking = false;
}
}
}
答案 1 :(得分:0)
System.Threading.ManualResetEvent
可能会在这里提供帮助。只需对它做一个WaitOne()。如果它被使用,那么它将返回为假。如果它没有使用它可用。
其中一个WaitOne()重载需要花费一些时间才能等待。如果你使用WaitOne(0),则等待将立即以非阻塞方式返回。
您应该对.Net提供的同步原语进行一些研究:
System.Threading.Monitor lock() { }
System.Threading.ManualResetEvent
System.Threading.AutoResetEvent
System.Threading.Semaphore
System.Threading.Mutex
答案 2 :(得分:0)
我认为你的方法通常应该是正确的,并且肯定比使用ManualResetEvent(如果它完全相关)要快得多 - 因为ManualResetEvent包装了底层的非托管原语。
为了使这种方法安全,_isWorking必须是私有的。