Потокобезопасный способ добавления и удаления элементов из списка в .Net

Я хочу добавить элементы в список из одного потока, а из другого потока удалить элементы из того же списка. Однако я не уверен, что у меня возникнут проблемы с несколькими потоками, обращающимися к одному и тому же объекту. Я немного прочитал оператор блокировки, но я не уверен, как это реализовать. Короче говоря, вопрос в том, как мне обеспечить потокобезопасный доступ к моему списку.


person yuben    schedule 30.07.2009    source источник


Ответы (3)


Используйте SyncRoot в IList:

lock(SomeList.SyncRoot) {...}
person Chernikov    schedule 30.07.2009
comment
Я не думаю, что в IList есть SyncRoot, не так ли? Это просто ArrayLists? - person Russell Troywest; 30.07.2009
comment
Да, это так. Это явная реализация интерфейса. ((IList)someList).SyncRoot - person bruno conde; 30.07.2009

Если вы используете систему производителя/потребителя — и похоже, что вы — синхронизированная очередь звучит как более подходящая структура, чем список.

person Steve Gilham    schedule 30.07.2009
comment
Я пытаюсь это сделать, но в .net 3.5 кажется, что Synchronized удален. - person Almo; 13.12.2011

Вот ЧРЕЗВЫЧАЙНО грубый пример блокировки. Оба потока теперь безопасны при добавлении и удалении из списка. Это не пример того, как создавать и использовать потоки — просто пример того, как использовать блокировку.

  Class A{
            private List<int> _list = new List<int>();

            private void DoOtherThreadWork() {
                while (true) {
                    //so something with thread. Sleep it, whatever...
                    lock(_list) {
                        _list.Add(1);
                    }
                }    
            }

            private void StartWorking(object sender, EventArgs e) {
                Thread worker = new Thread(DoOtherThreadWork);
                worker.Start();

                while (true) {
                    lock(_list) {
                        if (_list.Count > 0) {
                            _list.RemoveAt(0);
                        }
                    }
                }
            }
    }

Я, вероятно, также должен добавить, что для чего-то более сложного, чем этот базовый пример, вы можете использовать другой объект для самого списка.

private object lockObj = new Object();
        private void DoOtherThreadWork() {
                while (true) {
                    //so something with thread. Sleep it, whatever...
                    lock(_lockObj ) {
person Russell Troywest    schedule 30.07.2009