Monitor.Enter 方法

在指定对象上获取排他锁。

**命名空间:**System.Threading
**程序集:**mscorlib(在 mscorlib.dll 中)

语法

声明
Public Shared Sub Enter ( _
    obj As Object _
)
用法
Dim obj As Object

Monitor.Enter(obj)
public static void Enter (
    Object obj
)
public:
static void Enter (
    Object^ obj
)
public static void Enter (
    Object obj
)
public static function Enter (
    obj : Object
)

参数

  • obj
    在其上获取监视器锁的对象。

异常

异常类型 条件

ArgumentNullException

obj 参数为 空引用(在 Visual Basic 中为 Nothing)。

备注

使用 Enter 获取作为参数传递的对象上的 Monitor。如果其他线程已对该对象执行了 Enter,但尚未执行对应的 Exit,则当前线程将阻止,直到对方线程释放该对象。同一线程在不阻止的情况下多次调用 Enter 是合法的;但在该对象上等待的其他线程取消阻止之前必须调用相同数目的 Exit

使用 Monitor 锁定对象(即引用类型)而不是值类型。将值类型变量传递给 Enter 时,它被装箱为对象。如果再次将相同的变量传递给 Enter,则它被装箱为一个单独对象,而且线程不会阻止。Monitor 本应保护的代码未受保护。此外,将变量传递给 Exit 时,也创建了另一个单独对象。因为传递给 Exit 的对象和传递给 Enter 的对象不同,Monitor 将引发 SynchronizationLockException。有关详细信息,请参见概念性主题 监视器

Interrupt 可以中断正等待进入对象的 Monitor 的线程。将引发 ThreadInterruptedException

使用 C# tryfinally 块(在 Visual Basic 中为 TryFinally)来确保释放监视器,或使用以 tryfinally 块包装 Exit 方法的 C# lock 语句(在 Visual Basic 中为 SyncLock)。

示例

下面的示例说明如何使用 Enter 方法。

Imports System
Imports System.Threading
Imports System.Collections


Class MonitorSample
    'Define the queue to safe thread access.
    Private m_inputQueue As Queue

    Public Sub New()
        m_inputQueue = New Queue()
    End Sub

    'Add an element to the queue and obtain the monitor lock for the queue object.
    Public Sub AddElement(ByVal qValue As Object)
        'Lock the queue.
        Monitor.Enter(m_inputQueue)
        'Add an element.
        m_inputQueue.Enqueue(qValue)
        'Unlock the queue.
        Monitor.Exit(m_inputQueue)
    End Sub

    'Try to add an element to the queue.
    'Add the element to the queue only if the queue object is unlocked.
    Public Function AddElementWithoutWait(ByVal qValue As Object) As Boolean
        'Determine whether the queue is locked.
        If Not Monitor.TryEnter(m_inputQueue) Then
            Return False
        Else
            m_inputQueue.Enqueue(qValue)
            Monitor.Exit(m_inputQueue)
            Return True
        End If
    End Function

    'Try to add an element to the queue. 
    'Add the element to the queue only if during the specified time the queue object will be unlocked.
    Public Function WaitToAddElement(ByVal qValue As Object, ByVal waitTime As Integer) As Boolean
        'Wait while the queue is locked.
        If Not Monitor.TryEnter(m_inputQueue, waitTime) Then
            Return False
        Else
            m_inputQueue.Enqueue(qValue)
            Monitor.Exit(m_inputQueue)
            Return True
        End If
    End Function

    'Delete all elements that equal the given object and obtain the monitor lock for the queue object.
    Public Sub DeleteElement(ByVal qValue As Object)
        'Lock the queue.
        Monitor.Enter(m_inputQueue)
        Dim counter As Integer = m_inputQueue.Count
        While (counter > 0)  
            'Check each element.
            Dim elm As Object = m_inputQueue.Dequeue()
            If Not elm.Equals(qValue) Then
                m_inputQueue.Enqueue(elm)
            End If
            counter = counter - 1
        End While
        'Unlock the queue.
        Monitor.Exit(m_inputQueue)
    End Sub

    'Print all queue elements.
    Public Sub PrintAllElements()
        'Lock the queue.
        Monitor.Enter(m_inputQueue)
        Dim elmEnum As IEnumerator = m_inputQueue.GetEnumerator()
        While elmEnum.MoveNext()
            'Print the next element.
            Console.WriteLine(elmEnum.Current.ToString())
        End While
        'Unlock the queue.
        Monitor.Exit(m_inputQueue)
    End Sub

    Public Shared Sub Main()
        Dim sample As MonitorSample = New MonitorSample()
        Dim i As Integer

        For i = 0 To 29
            sample.AddElement(i)
        Next i
        sample.PrintAllElements()
        sample.DeleteElement(0)
        sample.DeleteElement(10)
        sample.DeleteElement(20)
        sample.PrintAllElements()
    End Sub

End Class
using System;
using System.Collections;
using System.Threading;

namespace MonitorCS2
{
    /// <summary>
    /// Summary description for Class1.
    /// </summary>
    class MonitorSample
    {
        //Define the queue to safe thread access.
        private Queue m_inputQueue;

        public MonitorSample()
        {
            m_inputQueue = new Queue(); 
        }

        //Add an element to the queue and obtain the monitor lock for the queue object.
        public void AddElement(object qValue)
        {
            //Lock the queue.
            Monitor.Enter(m_inputQueue);
            //Add element
            m_inputQueue.Enqueue(qValue);
            //Unlock the queue.
            Monitor.Exit(m_inputQueue);
        }

        //Try to add an element to the queue.
        //Add the element to the queue only if the queue object is unlocked.
        public bool AddElementWithoutWait(object qValue)
        {
            //Determine whether the queue is locked 
            if(!Monitor.TryEnter(m_inputQueue))
                return false;
            m_inputQueue.Enqueue(qValue);

            Monitor.Exit(m_inputQueue);
            return true;
        }

        //Try to add an element to the queue. 
        //Add the element to the queue only if during the specified time the queue object will be unlocked.
        public bool WaitToAddElement(object qValue, int waitTime)
        {
            //Wait while the queue is locked.
            if(!Monitor.TryEnter(m_inputQueue,waitTime))
                return false;
            m_inputQueue.Enqueue(qValue);
            Monitor.Exit(m_inputQueue);

            return true;
        }
        
        //Delete all elements that equal the given object and obtain the monitor lock for the queue object.
        public void DeleteElement(object qValue)
        {
            //Lock the queue.
            Monitor.Enter(m_inputQueue);
            int counter = m_inputQueue.Count;
            while(counter > 0)
            {   
                //Check each element.
                object elm = m_inputQueue.Dequeue();
                if(!elm.Equals(qValue))
                {
                    m_inputQueue.Enqueue(elm);
                }
                --counter;
            }
            //Unlock the queue.
            Monitor.Exit(m_inputQueue);
        }
        
        //Print all queue elements.
        public void PrintAllElements()
        {
            //Lock the queue.
            Monitor.Enter(m_inputQueue);            
            IEnumerator elmEnum = m_inputQueue.GetEnumerator();
            while(elmEnum.MoveNext())
            {
                //Print the next element.
                Console.WriteLine(elmEnum.Current.ToString());
            }
            //Unlock the queue.
            Monitor.Exit(m_inputQueue); 
        }

        static void Main(string[] args)
        {
            MonitorSample sample = new MonitorSample();
            
            for(int i = 0; i < 30; i++)
                sample.AddElement(i);
            sample.PrintAllElements();
            sample.DeleteElement(0);
            sample.DeleteElement(10);
            sample.DeleteElement(20);
            sample.PrintAllElements();

        }
    }
}
using namespace System;
using namespace System::Collections;
using namespace System::Threading;

// Class definition
public ref class MonitorSample
{
public:
   MonitorSample();
   void AddElement( Object^ qValue );
   bool AddElementWithoutWait( Object^ qValue );
   bool WaitToAddElement( Object^ qValue, int waitTime );
   void DeleteElement( Object^ qValue );
   void PrintAllElements();

private:
   Queue^ m_inputQueue;
};


//Define the queue to safe thread access.
MonitorSample::MonitorSample()
{
   m_inputQueue = gcnew Queue;
}


//Add an element to the queue and obtain the monitor lock for the queue object.
void MonitorSample::AddElement( Object^ qValue )
{
   
   //Lock the queue.
   Monitor::Enter( m_inputQueue );
   
   //Add element
   m_inputQueue->Enqueue( qValue );
   
   //Unlock the queue.
   Monitor::Exit( m_inputQueue );
}


//Try to add an element to the queue.
//Add the element to the queue only if the queue object is unlocked.
bool MonitorSample::AddElementWithoutWait( Object^ qValue )
{
   
   //Determine whether the queue is locked 
   if (  !Monitor::TryEnter( m_inputQueue ) )
      return false;

   m_inputQueue->Enqueue( qValue );
   Monitor::Exit( m_inputQueue );
   return true;
}


//Try to add an element to the queue. 
//Add the element to the queue only if during the specified time the queue object will be unlocked.
bool MonitorSample::WaitToAddElement( Object^ qValue, int waitTime )
{
   
   //Wait while the queue is locked.
   if (  !Monitor::TryEnter( m_inputQueue, waitTime ) )
      return false;

   m_inputQueue->Enqueue( qValue );
   Monitor::Exit( m_inputQueue );
   return true;
}


//Delete all elements that equal the given object and obtain the monitor lock for the queue object.
void MonitorSample::DeleteElement( Object^ qValue )
{
   
   //Lock the queue.
   Monitor::Enter( m_inputQueue );
   int counter = m_inputQueue->Count;
   while ( counter > 0 )
   {
      
      //Check each element.
      Object^ elm = m_inputQueue->Dequeue();
      if (  !elm->Equals( qValue ) )
      {
         m_inputQueue->Enqueue( elm );
      }

      --counter;
   }

   Monitor::Exit( m_inputQueue );
}


//Print all queue elements.
void MonitorSample::PrintAllElements()
{
   
   //Lock the queue.
   Monitor::Enter( m_inputQueue );
   IEnumerator^ elmEnum = m_inputQueue->GetEnumerator();
   while ( elmEnum->MoveNext() )
   {
      
      //Print the next element.
      Console::WriteLine( elmEnum->Current->ToString() );
   }

   Monitor::Exit( m_inputQueue );
}

int main()
{
   MonitorSample^ sample = gcnew MonitorSample;
   for ( int i = 0; i < 30; i++ )
      sample->AddElement( i );
   sample->PrintAllElements();
   sample->DeleteElement( 0 );
   sample->DeleteElement( 10 );
   sample->DeleteElement( 20 );
   sample->PrintAllElements();
}
package MonitorJSL2;

import System.*;
import System.Collections.*;
import System.Threading.*;

/// <summary>
/// Summary description for Class1.
/// </summary>
    
class MonitorSample
{
    //Define the queue to safe thread access.
    private Queue mInputQueue;

    public MonitorSample()
    {
        mInputQueue = new Queue();
    } //MonitorSample

    // Add an element to the queue and obtain the monitor lock for the 
    // queue object.
    public void AddElement(Object qValue)
    {
        //Lock the queue.
        Monitor.Enter(mInputQueue);

        //Add element
        mInputQueue.Enqueue(qValue);

        //Unlock the queue.
        Monitor.Exit(mInputQueue);
    } //AddElement

    //Try to add an element to the queue.
    //Add the element to the queue only if the queue object is unlocked.
    public boolean AddElementWithoutWait(Object qValue)
    {
        //Determine whether the queue is locked 
        if (!(Monitor.TryEnter(mInputQueue))) {
            return false;
        }
        mInputQueue.Enqueue(qValue);
        Monitor.Exit(mInputQueue);
        return true;
    } //AddElementWithoutWait

    //Try to add an element to the queue. 
    //Add the element to the queue only if during the specified time the 
    //queue object will be unlocked.
    public boolean WaitToAddElement(Object qValue, int waitTime)
    {
        //Wait while the queue is locked.
        if (!(Monitor.TryEnter(mInputQueue, waitTime))) {
            return false;
        }
        mInputQueue.Enqueue(qValue);
        Monitor.Exit(mInputQueue);

        return true;
    } //WaitToAddElement

    //Delete all elements that equal the given object and obtain the 
    //monitor lock for the queue object.
    public void DeleteElement(Object qValue)
    {
        //Lock the queue.
        Monitor.Enter(mInputQueue);
        int counter = mInputQueue.get_Count();
        while (counter > 0) {
            //Check each element.
            Object elm = mInputQueue.Dequeue();
            if (!(elm.Equals(qValue))) {
                mInputQueue.Enqueue(elm);
            }
            --counter;
        }

        //Unlock the queue.
        Monitor.Exit(mInputQueue);
    } //DeleteElement

    //Print all queue elements.
    public void PrintAllElements()
    {
        //Lock the queue.
        Monitor.Enter(mInputQueue);
        IEnumerator elmEnum = mInputQueue.GetEnumerator();
        while (elmEnum.MoveNext()) {
            //Print the next element.
            Console.WriteLine(elmEnum.get_Current().ToString());
        }

        //Unlock the queue.
        Monitor.Exit(mInputQueue);
    } //PrintAllElements

    public static void main(String[] args)
    {
        MonitorSample sample = new MonitorSample();

        for (int i = 0; i < 30; i++) {
            sample.AddElement((Int32)i);
        }
        sample.PrintAllElements();
        sample.DeleteElement((Int32)0);
        sample.DeleteElement((Int32)10);
        sample.DeleteElement((Int32)20);
        sample.PrintAllElements();
    } //main 
} //MonitorSample

平台

Windows 98、Windows 2000 SP4、Windows CE、Windows Millennium Edition、Windows Mobile for Pocket PC、Windows Mobile for Smartphone、Windows Server 2003、Windows XP Media Center Edition、Windows XP Professional x64 Edition、Windows XP SP2、Windows XP Starter Edition

.NET Framework 并不是对每个平台的所有版本都提供支持。有关受支持版本的列表,请参见系统要求

版本信息

.NET Framework

受以下版本支持:2.0、1.1、1.0

.NET Compact Framework

受以下版本支持:2.0、1.0

请参见

参考

Monitor 类
Monitor 成员
System.Threading 命名空间
Thread

其他资源

托管线程处理
监视器