C # Синхронизировать методы ожидания / опроса - PullRequest
0 голосов
/ 01 августа 2010

У меня есть класс, который предоставляет два метода:

- GetObject

Получает один объект или возвращает ноль, если его нет.

- WaitForObject

Получает отдельный объект или ждет, пока их не станет.

Пример реализации:

    class MyClass
    {
        MyStack stack;
        public object GetObject()
        {
            return stack.Pop();
        }
        public object WaitForObject()
        {
            object returnValue;
            while (returnValue == null)
                returnValue = stack.Pop()
            return returnValue
        }
    }

Если предположить, что MyStack является поточно-ориентированным, как я могу сделать MyClass поточно-безопасным? * 1020 Т.е. *

- GetObject никогда не должен блокироваться - Thread выполнение WaitForObject должно добавить все новые объекты в стек вместо GetObject.

Что касается бонусных баллов, как пользователи, добавляющие объекты в стек, могут уведомлять слушателей о наличии нового объекта? (исключая необходимость опроса)

Ответы [ 3 ]

1 голос
/ 01 августа 2010

Я думаю, что вы можете достичь всего с помощью функции монитора.просто эскиз

class MyClass
{
    private Stack<object> stack = new Stack<object>();
    public object GetObject()
    {
        lock(stack)
        {
            return stack.Count != 0 ? stack.Pop() : null;
        }
    }
    public object WaitForObject()
    {
        lock (stack)
        {
            if (stack.Count == 0)
            {
                // wait until PutObject is called
                Monitor.Wait(stack);
            }

            return stack.Pop();
        }
    }

    public void PutObject(object obj)
    {
        lock (stack)
        {
            stack.Push(obj);
            // notify one thread blocked by WaitForObject call
            Monitor.Pulse(obj);
        }
    }
}
1 голос
/ 01 августа 2010

Если MyStack гарантированно безопасен для потоков, то MyClass также безопасен для потоков. В двух методах вы используете только локальные переменные, поэтому эти методы являются реентерабельными.

В настоящее время пользователи не могут добавлять объекты в стек, поскольку поле stack не отображается вне класса. Также я не вижу из вашего кода, как слушатели будут подписываться на любые события, чтобы они были уведомлены, если объект добавлен. Таким образом, у вас может быть метод, позволяющий добавлять элементы в стек, и событие, которое будет вызвано в этом случае.

0 голосов
/ 01 августа 2010

Опрос обычно включает в себя некоторую форму сна - петля в вашем примере будет жесткой петлей, которая будет задушить thead все время. Добавьте Thread.Sleep(100) вызов или другое разумное значение для опроса во времени.

Другим способом ожидания будет регистрация обратного вызова или стек, предоставляющий блокирующий метод Pop, так или иначе, они будут реализованы в классе Stack в вашем примере.

Бонусный ответ: Вашему классу нужно будет выставить событие, когда они добавят объект в стек, оно вызовет это событие.

class MyClass 
    { 
        MyStack stack; 
        public object GetObject() 
        { 
            return stack.Pop(); 
        } 
        public object WaitForObject() 
        { 
            object returnValue; 
            while (returnValue == null) 
                returnValue = stack.Pop() 
            return returnValue 
        } 
        public void AddObject(object o)
        {
            stack.Push(o);
            OnObjectAdded();
        }
        public event EventHandler ObjectAdded;

        private void OnObjectAdded()
        {
            if (ObjectAdded != null)
                ObjectAdded(this, EventArgs.Empty);
        }
    } 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...