Пожалуйста, кто-нибудь может дать мне простой пример того, как использовать System.Monitor в C #? - PullRequest
4 голосов
/ 23 октября 2008

Я нахожу System.Monitor очень запутанным, хотя я понимаю многопоточность, блокировки, взаимоблокировки, условия гонки, обедающие философы и весь этот джаз. Обычно я использую ManualResetEvent () для координации между потоками, но я знаю, что это тяжелый объект ядра, и что System.Monitor (Enter / Pulse и т. Д.) Гораздо эффективнее. Я гуглил и гуглил, но не могу найти разумного примера.

Буду очень признателен, если команда СО сможет объяснить мне эту потенциально замечательную конструкцию: -)

Ответы [ 2 ]

8 голосов
/ 23 октября 2008

Вот очень простой пример; вызов Wait снимает блокировку (позволяя Worker получить ее) и добавляет поток Main в очередь ожидания объекта блокировки. Worker затем получает блокировку и вызывает Pulse: это перемещает поток Main в очередь готовности объекта блокировки. Когда Worker снимает блокировку, Main может возобновить работу.

Обратите внимание, что lock(obj) {...} это просто конфетка компилятора для Monitor.Enter / Monitor.Exit в блоке try / finally.

[править: я изменил семпл, чтобы переместить lock(sync) ранее, чтобы избежать (маловероятного) риска пропущенного импульса]

    static void Main()
    {
        object sync = new object();
        lock (sync)
        {
            ThreadPool.QueueUserWorkItem(Worker, sync);
            Console.WriteLine("Main sleeping");

            // wait for the worker to tell us it is ready
            Monitor.Wait(sync);
            Console.WriteLine("Main woke up!");
        }
        Console.WriteLine("Press any key...");
        Console.ReadKey();
    }
    static void Worker(object sync)
    {
        Console.WriteLine("Worker started; about to sleep");
        Thread.Sleep(5000);
        Console.WriteLine("Worker about pulse");
        lock (sync)
        { // notify Main that we did something interesting
            Monitor.Pulse(sync);
            Console.WriteLine("Worker pulsed; about to release lock");
        }
        Console.WriteLine("Worker all done");
    }
3 голосов
/ 23 октября 2008

Посмотрите, поможет ли эта часть моей статьи о потоках ... (вторая половина этой страницы). Он реализует очередь производителя / потребителя: когда производитель создает что-то в очереди (и находит, что это было пусто - в качестве оптимизации), он заставляет монитор пробуждать любые ожидающие потоки. Когда потребитель пытается получить данные из очереди, но обнаруживает, что она пуста, он ждет импульса, прежде чем пытаться снова.

В качестве альтернативы, В учебнике по потокам Джо Албахари есть также раздел "Ожидание / пульс".

Это очень похоже на то, к чему вы привыкли, в WaitHandle, хотя, честно говоря, мне легче разобраться, чем в WaitHandles, в основном потому, что это так похоже на ожидание / уведомление Java, с которым я "вырос" :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...