Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.86/21: Рейтинг темы: голосов - 21, средняя оценка - 4.86
64 / 65 / 44
Регистрация: 05.12.2014
Сообщений: 475

Обезопасить доступ к коллекции из разных потоков

02.12.2016, 12:52. Показов 4738. Ответов 37
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
станет ли безопасным метод AddSafe?
C#
1
2
3
4
5
6
7
8
9
10
11
12
public static MyCollection myCol = new MyCollection();
 
class MyCollection: ObservableCollection<string>
{
    public void AddSafe(string item)
    {
        lock(this)
        {
            this.Add(item);
        }
    }
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
02.12.2016, 12:52
Ответы с готовыми решениями:

Заполнение коллекции из разных потоков
Добрый день. Что я могу использовать вместо удобной ObservableCollection&lt;T&gt;, если мне надо добавлять данные из разных потоков?

Одновременный доступ к коллекции из двух потоков
Здравствуйте. В программе открываю UDP-сокет, в который приходят данные с устройства. Вкратце, у меня выглядит это так: public void...

Доступ к БД с разных потоков
как реализовать доступ к одной базе данных с разных потоков? когда один сервер обрабатывает несколько клиентов то у меня выходит...

37
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
02.12.2016, 14:38
Цитата Сообщение от Jotun Посмотреть сообщение
станет ли безопасным метод AddSafe?
Да, только не используйте lock (this). Лучше создайте закрытый readonly-объект и замыкайтесь на нем.
Ну и учтите, что у вас замыкание будет держаться до тех пор, пока не отработают все подписчики на события.
1
64 / 65 / 44
Регистрация: 05.12.2014
Сообщений: 475
04.12.2016, 11:59  [ТС]
Но всё равно это похоже не выход. Если я хочу только изменить конкретный объект в коллекции - то нужен будет lock
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
04.12.2016, 21:22
Цитата Сообщение от Jotun Посмотреть сообщение
Но всё равно это похоже не выход.
Что именно?
0
64 / 65 / 44
Регистрация: 05.12.2014
Сообщений: 475
04.12.2016, 22:49  [ТС]
Цитата Сообщение от kolorotur Посмотреть сообщение
Что именно?
да, непонятно написал

Просто хотел уменьшить количество локов разбросанных по коду и собрать их внутри коллекции.
0
139 / 139 / 53
Регистрация: 14.06.2016
Сообщений: 467
05.12.2016, 06:25
Цитата Сообщение от Jotun Посмотреть сообщение
Просто хотел уменьшить количество локов разбросанных по коду и собрать их внутри коллекции.
Ну так собери. Вот пример реализации http://theburningmonk.com/2010... in-csharp/
Правда у меня в релизном проекте всё равно довольно часто бросалось исключение (коллекция изменена), хз почему.
0
Эксперт .NET
 Аватар для Usaga
14138 / 9367 / 1350
Регистрация: 21.01.2016
Сообщений: 35,246
05.12.2016, 07:06
Цитата Сообщение от Jotun Посмотреть сообщение
Просто хотел уменьшить количество локов разбросанных по коду и собрать их внутри коллекции.
Мало того, что эти локи и должны быть в одном месте, так ещё можно обойтись и без локов, если коллекция только читается: ReaderWriterLockSlim.
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
05.12.2016, 10:30
Jotun, А может сразу BlockingCollection использовать?
0
64 / 65 / 44
Регистрация: 05.12.2014
Сообщений: 475
05.12.2016, 11:19  [ТС]
Цитата Сообщение от aquaMakc Посмотреть сообщение
otun, А может сразу BlockingCollection использовать?
Я бы с удовольствием но нужно выводить данные в элементы ui
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
05.12.2016, 11:21
Jotun, используй для этого отдельный класс-обёртку данных. И формируй коллекцию обёрток на основе коллекции данных (LINQ`ом это вообще элементарно делается).
0
64 / 65 / 44
Регистрация: 05.12.2014
Сообщений: 475
31.07.2017, 22:47  [ТС]
Может кто-то рассказать о BindingOperations.EnableCollectionSynchr onization - https://msdn.microsoft.com/en-... .110).aspx

Если я правильно понял, то достаточно вызвать данный метод для коллекции и можно не парится с локами?
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
01.08.2017, 11:01
Цитата Сообщение от Jotun Посмотреть сообщение
Если я правильно понял, то достаточно вызвать данный метод для коллекции и можно не парится с локами?
Нет, данный метод всего лишь предоставляет системе привязки объект для синхронизации доступа к коллекции, поскольку вы не можете лочить ее сами.
Во всех остальных многопоточных случаях коллекцию все равно придется лочить. И если вы пользуетесь данным методом, то лучше лочить ее на тот же объект, ссылка на который была передана вторым аргументом в EnableCollectionSynchronization.
1
64 / 65 / 44
Регистрация: 05.12.2014
Сообщений: 475
01.08.2017, 18:33  [ТС]
Цитата Сообщение от kolorotur Посмотреть сообщение
Нет, данный метод всего лишь предоставляет системе привязки объект для синхронизации доступа к коллекции, поскольку вы не можете лочить ее сами.
То есть если у меня есть коллекция привязанная к элементу интерфейса, и котороя может изменятся в другом потоке, то нужно вызывать этот метод чтобы всё было нормально?
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
01.08.2017, 18:35
Цитата Сообщение от Jotun Посмотреть сообщение
То есть если у меня есть коллекция привязанная к элементу интерфейса, и котороя может изменятся в другом потоке, то нужно вызывать этот метод чтобы всё было нормално?
Вызвать этот метод достаточно один раз.
Но в отдельном потоке надо будет лочить коллекцию при ее изменении.
0
64 / 65 / 44
Регистрация: 05.12.2014
Сообщений: 475
01.08.2017, 19:27  [ТС]
Цитата Сообщение от kolorotur Посмотреть сообщение
Вызвать этот метод достаточно один раз.
Да, я понял, просто сам принцип пытаюсь понять
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
02.08.2017, 10:04
Цитата Сообщение от Jotun Посмотреть сообщение
сам принцип пытаюсь понять
При доступе к коллекции из разных потоков необходимо этот доступ синхронизировать, если коллекция не является потокобезопасной.

Если коллекцией пользуетесь только вы, то все просто: достаточно определить критические зоны, в которых производится работа с коллекцией, проще всего это делается конструкцией lock.

Все становится малость сложнее, когда этой же коллекцией начинает пользоваться код, реализующий отрисовку пользовательского интерфейса, то есть "кишки" WPF.

Здесь у вас практически нет никакого контроля над тем, когда будет произведена переотрисовка интерфейса и как следствие будет произведен доступ к коллекции из внутренностей WPF. Получается, что вся синхронизация доступа сразу теряет смысл, т.к. она работает только тогда, когда доступ к общему ресурсу синхронизирован везде, а не где-либо выборочно.

Метод EnableCollectionSynchronization фактически просто передает во внутренности фреймворка ссылку на объект, на котором WPF будет замыкаться каждый раз при работе с вашей коллекцией, потому и передавать туда нужно ту же ссылку, которую вы используете для замыкания при работе с коллекцией в ваших потоках.

Дополнительно этот метод включает маршаллинг обработки событий коллекции в GUI-поток.

Никакой магии.
1
64 / 65 / 44
Регистрация: 05.12.2014
Сообщений: 475
07.08.2017, 15:20  [ТС]
Что-то не получается у меня нифига.
Сделал вот такую коллекцию:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    public class AutoSkillUseCollection : ObservableCollection<AutoSkillListItem>
    {
        private object _lock = new object();
 
        public void AddSafe(AutoSkillListItem item)
        {
            lock (_lock)
                this.Add(item);
        }
 
        public void RemoveSafe(AutoSkillListItem item)
        {
            lock (_lock)
                this.Remove(item);
        }
 
        public void TryToLaunchSelfHeal()
        {
            lock (_lock)
                foreach (AutoSkillListItem item in this)
                    if (item.SkillType == AutoSkillTypes.SelfHeal)
                        (item as SelfHealListItem).TryToLaunch();
        }
 
        // куча подобных функций залоченых _lock
}
Переодически прога зависает при нажатии на кнопку Add или кнопку с крестиком. Пауза вижуал студии показывает на _lock в методах AddSafe или RemoveSafe соответственно. Методы коллекции (кроме AddSafe и RemoveSafe) могут вызываться из другого потока. Почему оно виснет а не дожидается отпуска лока не понимаю
Миниатюры
Обезопасить доступ к коллекции из разных потоков  
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
07.08.2017, 16:02
Цитата Сообщение от Jotun Посмотреть сообщение
куча подобных функций залоченых _lock
Наверное, где-то в этой куче что-то делается не так.
Метод EnableCollectionSynchronization был вызван? Если да, то какая ссылка была в него передана в качестве объекта для синхронизации?
Интересно так же что делается в методе TryToLaunch класса SelfHealListItem.

Похоже, у вас где-то конфликт замыканий и приложение виснет наглухо.
0
64 / 65 / 44
Регистрация: 05.12.2014
Сообщений: 475
07.08.2017, 16:34  [ТС]
Цитата Сообщение от kolorotur Посмотреть сообщение
Метод EnableCollectionSynchronization был вызван? Если да, то какая ссылка была в него передана в качестве объекта для синхронизации?
Сначала нет, попробовал передать туда этот _lock сделав его public но не проканало.
Цитата Сообщение от kolorotur Посмотреть сообщение
нтересно так же что делается в методе TryToLaunch класса SelfHealListItem.
да там много чего делается, я даже не знаю как стороннему человеку понять что-то в уже большой программе....
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
        public void TryToLaunch(string name)
        {
            if (!IsEnabled) return;
            if (!IsReady) return;
            if (NameList.Count < 1 || Guids.Count < 1) return;
            if (!NameList.ContainsCheckedName(name)) return;
 
            Guid guid;
            if (Guids.ContainsKey(name))
                guid = Guids[name];
            else
                return;
            
            if (Vars.RequestList.ContainsGuid(guid)) return;
            
            L2PartyMember pm;
            pm = Vars.PartyList.GetItemByName(name);
            if (pm == null) return;
            if (!Vars.CreaturesList.ContainsObjectID(pm.objId)) return;
            
            int max = 0, val = 0;
 
            switch (HealType)
            {
                case HealTypes.HP: max = pm.MaxHP; val = pm.HP; break;
                case HealTypes.MP: max = pm.MaxMP; val = pm.MP; break;
                case HealTypes.CP: max = pm.maxCP; val = pm.CP; break;
            }
            if (max == 0) return;
            int curPercents = val * 100 / max;
            if (curPercents <= Percents)
            {
                Request request = new Request(guid, MotherRequestType.Heal, IsNeedTarget, pm, false, Skill, Send.RequestMagicSkillUse(Skill.id, false));
                Vars.RequestList.AddSafe(request);
            }
            else
                TryToStop(name);
        }
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
07.08.2017, 17:36
Цитата Сообщение от Jotun Посмотреть сообщение
я даже не знаю как стороннему человеку понять что-то в уже большой программе
В основном высматриваю запуск каких-нибудь потоков или, не дай бог, асинхронные вызовы вперемешку с замыканиями.
Где-нибудь в вашем коде производится подписка на события этой коллекции?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
07.08.2017, 17:36
Помогаю со студенческими работами здесь

Доступ к очереди из разных потоков
Подскажите по многопоточности, у меня есть очередь (Queue) и мне надо организовать к ней доступ из разных потоков, выискал несколько...

Доступ к стриму из разных потоков
Задача такая, имеем мемористрим, в одном потоке постоянно пишем его. В другом потоке необходимо по запросу считывать весь поток в...

Доступ к функции с разных потоков C++ Builder
Как правильно объявить/создать функцию в C++Builder, чтобы она была доступна со всех потоков, включая главный? И как потом в этой функции...

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

Доступ к файлам из разных потоков, как исключить коллизии?
Разные потоки осуществляют чтение разных файлов произвольным образом командой System.IO.FileStream(NameFile, FileMode.Open). Иногда, при...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru