@vilix

Как лучше ждать(проверять) выполнения функции (Monitor.Enter vs While(var))?

Привет всем, у меня при написании WCF сервиса, возникла следующая задача: есть метод1, который может выполнятся длительное время, вызываться он может из любого instance, но требуется, чтобы в работе этот метод мог быть только один. Эту часть я решил через isBusy=true в начале и isBusy=false в конце. Эта часть работает.

Self-hosted консольное приложение вызывает периодически некоторые методы, которые не должны выполнятся одновременно с методом1. Т.е если метод1 выполняется, то ждем пока он закончит и дальше запускаем эти методы. И тут я задумался, что лучше использовать и есть ли вообще разница, либо ожидать пока isBusy=true. Либо создать busyLock.

Ниже пример тестового приложения, которое выполняет то, что мне нужно, двумя разными методами.

static bool isBusy = true;
        static object busyLock = new object();

        static void Main(string[] args)
        {
            new Task(longTaks1).Start();
            while (isBusy) { }
            taskMustRunOnlyWhenLongTaskNotRunning();

            new Task(longTaks2).Start();
            Monitor.Enter(busyLock);
            taskMustRunOnlyWhenLongTaskNotRunning();

            Console.ReadLine();
        }

        static void taskMustRunOnlyWhenLongTaskNotRunning()
        {
            Console.WriteLine("taskMustRunOnlyWhenLongTaskNotRunning");
        }

        static void longTaks1()
        {
            isBusy = true;
            Thread.Sleep(5000);
            isBusy = false;
        }

        static void longTaks2()
        {
            Monitor.Enter(busyLock);
            Thread.Sleep(5000);
            Monitor.Exit(busyLock);
        }


Вопрос скорее в том, есть ли существенная разница в подходах и какие подводные камни. Спасибо за ответы.

P.S isBusy на сервисе я храню в поле потокобезопастного синглтона.
  • Вопрос задан
  • 270 просмотров
Решения вопроса 2
petermzg
@petermzg
Самый лучший программист
Используйте для этого Event. Скинули сигнальное состояние, сервис занят.
Для вашей задачи лучше ManualResetEvent. Сервис выполнил задачу и сам установил сигнальное состояние.
В других потоках будете просто писать
event.WaitOne(<кол-во миллисекунд>);
Если нет сигнального состояния, ваш поток уснет на нужное время и проснется когда сервис завершит работу и установит сигнальное состояние или по истечению времени ожидания.
Ответ написан
1.Если не используете lock, а руками пишите Enter exit, реализация неверная и не безопасная, гугл try finally taken.
2. While busy загрузит процессор (почти всегда)
Советую почитать что-что, судя по вопросу , в этой теме Вы новичок.
Все выше написанное абстрагированно от задач и wcf.
3. Busy использование не корректно в Вашем коде.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
EreminD
@EreminD
Кое-что умею
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы