我正在尝试找到一种提供对资源的独家访问的方法,同时提供有关锁状态(_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结构为此目的进行改编?

以及如何实现“真实”锁定方案,在第一个线程完成后,第二个线程仍将执行该方法,同时提供有关状态的信息?

有帮助吗?

解决方案

假设我正确理解了您的问题,那么我认为您是什么 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;
    }
  }
}

其他提示

System.Threading.ManualResetEvent 也许可以在这里提供帮助。只需对此做一个waitone()。如果使用它,它将返回为false。如果不使用它,则可以使用。

WaitOne()超载之一需要花费一些时间才能等待。如果您使用Waitone(0),则等待将立即以非阻止方式返回。

您应该对.NET提供的同步基元进行一些研究:

System.Threading.Monitor lock() { }
System.Threading.ManualResetEvent
System.Threading.AutoResetEvent
System.Threading.Semaphore
System.Threading.Mutex

我认为您的方法一般应该是正确的,并且肯定会比使用ManualResetevent(如果它完全相关)要快得多 - 因为手动Resetevent包裹了无管理的原始原始内容。

但是,为了使这种方法安全,必须是私人的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top