이 페이지가 유용했습니까?
이 콘텐츠에 대한 여러분의 의견은 중요합니다. 의견을 알려주십시오.
추가 의견
1500자 남음
내보내기(0) 인쇄
모두 확장
정보
요청한 주제가 아래에 표시됩니다. 그러나 이 주제는 이 라이브러리에 포함되지 않습니다.

Monitor.Wait 메서드 (Object, Int32)

2013-12-13

개체의 잠금을 해제한 다음 잠금을 다시 가져올 때까지 현재 스레드를 차단합니다. 지정된 시간 제한 간격이 지나면 스레드가 준비된 큐에 들어갑니다.

Namespace:  System.Threading
어셈블리:  mscorlib(mscorlib.dll)

public static bool Wait(
	Object obj,
	int millisecondsTimeout
)

매개 변수

obj
형식: System.Object
대기할 개체입니다.
millisecondsTimeout
형식: System.Int32
스레드가 준비된 큐에 들어가기 전에 대기할 시간(밀리초)입니다.

반환 값

형식: System.Boolean
지정된 시간이 경과하기 전에 잠금을 다시 가져오면 true이고, 지정된 시간이 경과한 이후에 잠금을 다시 가져오면 false입니다. 이 메서드는 잠금을 다시 가져올 때까지 반환하지 않습니다.

예외조건
ArgumentNullException

obj 매개 변수가 null인 경우

SynchronizationLockException

호출한 스레드가 지정된 개체 잠금을 소유하지 않는 경우

ArgumentOutOfRangeException

millisecondsTimeout 매개 변수의 값이 음수이고 Infinite와 같지 않은 경우

이 메서드는 obj 매개 변수에 대한 단독 잠금을 다시 가져올 때까지 반환하지 않습니다.

현재 지정된 개체의 잠금을 소유하는 스레드는 다른 스레드에서 액세스할 수 있도록 해당 개체를 해제하기 위해 이 메서드를 호출합니다. 잠금을 다시 가져오기를 기다리는 동안 호출자가 차단됩니다. 이 메서드는 호출자가 다른 스레드 연산의 결과로 발생할 상태 변경을 기다려야 하는 경우 호출됩니다.

시간 제한이 있기 때문에 다른 스레드가 먼저 Pulse 또는 PulseAll 메서드를 호출하지 않고 잠금을 해제하는 경우 현재 스레드가 무기한 차단하지 않습니다. 또한 스레드를 준비된 큐로 이동하고 대기 큐에서 이 스레드 앞에 있는 다른 스레드를 무시하여 잠금을 더 빨리 다시 가져올 수 있습니다. 스레드는 Wait 메서드의 반환 값을 테스트하여 제한 시간 전에 잠금을 다시 가져왔는지 여부를 확인합니다. 스레드는 대기 상태로 들어가게 한 조건을 확인할 수 있으며 필요한 경우 Wait 메서드를 다시 호출합니다.

스레드에서 Wait를 호출하면 스레드는 개체 잠금을 해제하고 개체의 대기 중인 큐에 들어갑니다. 개체의 준비된 큐(있는 경우)에 있는 다음 스레드에서 잠금을 가져오고 개체를 단독으로 사용합니다. Wait를 호출한 스레드는 잠금을 보유한 스레드가 PulseAll을 호출하거나, 큐에서 다음 순서이고 잠금을 보유한 스레드가 PulseAll를 호출할 때까지 대기 중인 큐에 남아 있습니다. 그러나 다른 스레드에서 이 개체의 Pulse 또는 PulseAll 메서드를 호출하기 전에 millisecondsTimeout이 경과하면 잠금을 다시 가져오기 위해 원래 스레드가 준비된 큐로 이동합니다.

참고참고:

millisecondsTimeout 매개 변수에 Infinite를 지정하면 이 메서드는 잠금의 소유자가 Pulse 또는 PulseAll를 호출하지 않는 경우 무기한 차단합니다. millisecondsTimeout이 0이면 Wait를 호출하는 스레드에서 잠금을 해제한 다음 잠금을 다시 가져오기 위해 즉시 준비된 큐에 들어갑니다.

호출자는 지정된 개체에 대해 Enter가 호출된 횟수에 상관없이 Wait를 한 번 실행합니다. 개념적인 측면에서 Wait 메서드는 호출자가 개체에 Enter를 호출한 횟수를 저장하고, 잠겨 있는 개체를 완전히 해제하는 데 필요한 횟수만큼 Exit를 호출합니다. 그런 다음 호출자는 개체를 다시 가져오기를 기다리는 동안 차단합니다. 호출자가 잠금을 다시 가져오면 시스템에서는 저장된 호출자의 Enter 수를 복구하는 데 필요한 만큼 Enter를 호출합니다. Wait를 호출하면 지정된 개체 잠금만 해제됩니다. 호출자가 다른 개체의 잠금을 소유한 경우 해당 잠금은 해제되지 않습니다.

참고참고:

동기화된 개체에는 현재 잠금을 보유한 스레드에 대한 참조, 잠금을 가져올 준비가 된 스레드를 포함하는 준비된 큐에 대한 참조, 개체의 상태 변경 알림을 기다리는 스레드를 포함하는 대기 중인 큐에 대한 참조 등 여러 개의 참조가 있습니다.

Pulse, PulseAllWait 메서드는 동기화된 코드 블록 내에서 호출해야 합니다.

Pulse 메서드에 대한 설명 부분에서는 대기 중인 스레드가 없을 때 Pulse를 호출한 경우에 발생하는 현상에 대해 설명합니다.

버전 메모

Windows Phone

사용자가 Windows Phone 응용프로그램 외부로 이동하면 응용프로그램은 일반적으로 유휴 상태가 됩니다. 사용자가 유휴 응용프로그램으로 돌아가면 응용프로그램은 자동으로 다시 시작됩니다. 이 API가 사용되는 동안 응용프로그램이 유휴 상태가 되면 API는 예상대로 완료되지 않습니다. 응용프로그램은 이 가능성을 처리하도록 디자인되어야 합니다. Windows Phone 실행 모델에 대한 자세한 내용은 Windows Phone의 실행 모델을 참조하세요.

다음 예제에서는 제한 시간이 있는 Wait 메서드 오버로드 사용 방법을 보여 줍니다. 공급자 스레드에서 더 이상 새 값을 제공하지 않으면 메서드는 시간 초과됩니다.

참고참고:

이 예제를 실행하려면 Windows Phone용 정적 TextBlock 컨트롤이 있는 예제 빌드를 참조하세요.


using System;
using System.Threading;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Input;
using System.Windows.Controls;

class Example
{
    const int MAX_ITERATIONS = 100;

    // Example data: A BackgroundWorker that reports progress to the user 
    // interface thread, the queue that is protected by the lock, and a
    // random number generator.
    private BackgroundWorker m_worker = new BackgroundWorker();
    private Queue<int> m_smplQueue = new Queue<int>();
    private Random m_random = new Random();

    // This thread does work and produces a result (in this case just a
    // number).
    private void Producer()
    {
        int counter = 0;
        lock (m_smplQueue)
        {
            while (counter < MAX_ITERATIONS)
            {
                // Wait, if the queue is busy.
                Monitor.Wait(m_smplQueue);

                // Simulate a small amount of work, then queue one element
                // and release the waiting thread.
                Thread.Sleep(10 + m_random.Next(10));
                m_smplQueue.Enqueue(counter);
                Monitor.Pulse(m_smplQueue);

                counter += 1;
            }
        }
    }

    // This thread consumes the result produced by the first thread. It 
    // could do additional processing, but in this case it just reports
    // the number.
    private void Consumer()
    {
        lock (m_smplQueue)
        {
            // Release the waiting thread.
            Monitor.Pulse(m_smplQueue);

            // Wait in the loop while the queue is busy.
            // Exit on the time-out when the first thread stops. 
            while (Monitor.Wait(m_smplQueue, 1000))
            {
                // Pop the first element.
                int counter = (int) m_smplQueue.Dequeue();

                // Print the first element.
                m_worker.ReportProgress(0, String.Format("{0} ", counter));

                // Release the waiting thread.
                Monitor.Pulse(m_smplQueue);
            }
        }
    }


    // -------------------
    // This section contains supporting code that runs the example on a
    // background thread, so it doesn't block the UI thread, and enables
    // the example to display output using Windows Phone UI elements. There
    // is no example code for Monitor in this section.

    // This UI element receives the output from the example. It's the same
    // for all instances of Example.
    private static TextBlock outputBlock;

    // A list of all Example objects that are currently running. 
    private static List<Example> examples = new List<Example>();

    // The Demo method saves the TextBlock used for output, and sets up a
    // mouse event that you click to run instances of the demonstration.
    //
    public static void Demo(TextBlock outputBlock)
    {
        Example.outputBlock = outputBlock;
        outputBlock.Text += "Click here to begin running the example.\r\n";

        // Set up an event handler to run the example when the TextBlock 
        // is clicked.
        outputBlock.MouseLeftButtonUp += MouseUp;
    }

    // This mouse event gives visual feedback and starts a new instance of
    // Example. The instance must be started on the UI thread, so that the
    // BackgroundWorker raises its events on the UI thread.
    //
    private static void MouseUp(object sender, MouseButtonEventArgs e)
    {
        outputBlock.Text += "<Click> ";
        examples.Add(new Example());
    }


    // Each new Example sets up the events for its background task and
    // launches the task. It also creates a unique ID number.
    //
    private int m_id;
    private static int lastId = 0;
    public Example()
    {
        m_id = Interlocked.Increment(ref lastId);

        m_worker.DoWork += this.RunExample;
        m_worker.WorkerReportsProgress = true;
        m_worker.ProgressChanged += this.Progress;
        m_worker.RunWorkerCompleted += this.Completed;
        m_worker.RunWorkerAsync();
    }

    // Launch the producer and consumer threads.
    private void RunExample(object sender, DoWorkEventArgs e)
    {

        // Create the threads and start them.
        Thread tProducer = new Thread(this.Producer);
        Thread tConsumer = new Thread(this.Consumer);
        tProducer.Start();
        Thread.Sleep(1);
        tConsumer.Start();

        // Wait until the two threads end.
        tProducer.Join();
        tConsumer.Join();

        // When the task completes, return the Example object.
        e.Result = this;
    }

    // The display output that is queued using the ReportProgress method
    // is delivered to the UI thread by this event handler.
    //
    private void Progress(object sender, ProgressChangedEventArgs e)
    {
        // This code is executed on the main UI thread, so it's safe to 
        // access the UI elements.
        outputBlock.Text += e.UserState.ToString();
    }

    // This event handler signals task completion to the UI thread. It 
    // removes the Example object from the list and displays its count.
    //
    private void Completed(object sender, RunWorkerCompletedEventArgs e)
    {
        examples.Remove(this);
        outputBlock.Text += String.Format("<Example({0}) Queue Count = {1}> ",
                                          m_id, m_smplQueue.Count);
    }
}

/* This code produces output similar to the following:

Click here to begin running the example.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 
30 <Click> 31 32 33 0 34 1 35 2 36 3 37 38 4 5 39 6 40 7 41 8 42 43 9 10 44 45 11
46 12 13 47 48 14 49 15 50 16 51 17 52 18 53 19 54 20 55 21 56 22 57 23 24 58 25
59 26 60 27 28 61 29 62 30 31 63 64 32 33 65 34 66 35 67 36 68 37 69 38 39 70 71 
40 41 72 42 73 74 43 75 44 76 77 45 46 78 47 79 48 80 49 81 50 82 51 83 52 84 53
85 54 86 55 87 56 88 57 89 58 90 59 91 60 92 61 93 62 94 63 95 64 65 96 97 66 98
67 99 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
93 94 95 96 97 98 99 <Example(1) Queue Count = 0> <Example(2) Queue Count = 0> 
 */


Windows Phone OS

지원되는 버전: 8.0, 7.1, 7.0

Windows Phone

표시:
© 2015 Microsoft