Блокировка () не эффективна - PullRequest
1 голос
/ 29 ноября 2010

Я пытаюсь заблокировать объект, пока он проходит через его элементы.Мой массив allThreads действительно не заблокирован, потому что во время выполнения «foreach» я получаю исключение, говорящее «Коллекция была изменена; операция перечисления может не выполняться».Я думал, что это была целая сделка с замком?

lock (mApp.allThreads)
{
    foreach (Thread t in mApp.allThreads)
        if (t.Name == "OpcDAWriter" && t != Thread.CurrentThread)
            t.Join(); 
}

Ответы [ 2 ]

3 голосов
/ 29 ноября 2010

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

Если вы хотите запретить одному потоку манипулировать коллекцией, пока другой поток итерирует по ней, вам нужно поместить итерационный код и код манипуляции в блоки lock, блокируя один и тот же объект. *

Простой образец:

class LockDemo
{
    private IList<string> _items;
    private object _lock = new object();
    public LockDemo()
    {
        _items = new List<string>(new[] { "one", "two", "three" });
    }

    public void RemoveItem(string item)
    {
        lock (_lock)
        {
            _items.Remove(item);
        }
    }

    public void DoSomethingThatIteratesOverTheList()
    {
        lock (_lock)
        {
            foreach (var item in _items)
            {
                // do something with item
            }
        }
    }
}

Обратите внимание, как весь доступ к списку (за исключением конструктора в данном случае) заключен в блоки lock, которые все блокируются на одном и том же объекте. Также обратите внимание, что этот объект не сам список, а объект, который используется только для целей блокировки. Это показывает, что lock не блокирует объект как таковой, но предоставляет механизм для управления тем, какие части кода могут или не могут выполняться параллельно различными потоками.

0 голосов
/ 29 ноября 2010

Вы присоединяетесь к потоку t, поэтому он, вероятно, удаляется из mApp.allThreads или что-то еще происходит из-за объединения, что приводит к изменению коллекции.

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

private readonly _lock = new object();

[...]
lock(_lock)
{
  foreach....
}

, но я сомневаюсь, что это что-то изменит.

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