Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
1 / 1 / 0
Регистрация: 14.03.2017
Сообщений: 6

Синхронизация двух очередей в мультипотоковом приложении

23.11.2018, 17:37. Показов 1212. Ответов 3
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Приветствую.
Сейчас пишу по работе сервер для работы с WEB Service ГИС ЖКХ. Суть проблемы, с которой не могу разобраться:
Есть класс своего "пула потоков", в котором крутятся 20 Task и дергают ConcurrentQueue<GisJobItem> на наличие работы.
Добавление в ConcurrentQueue происходит из отдельного класса асинхронного сервера, который по TCP получает инфо о "Job", которую надо выполнить и при получении корректного запроса добавляет, через вызов процедуры AddJob класса пула потоков.
Всё бы это замечательно работало, но, как всегда есть но!.
Мне надо держать еще одну коллекцию с теми Job, которые выполняются в данный момент. Т.к. пользователь клиента на той стороне, легко нажмет кнопку запуска 83 раза, если ему покажется, что ничего не работает.
И из-за этого пришлось вводить HashSet<GisJobItem>, но он не потокобезопасный. Пришлось через lock блочить 2 места:
1. Добавление новой Job.
2. Доставание Job из ConcurrentQueue. Вот это уже плохо. По большому счету ConcurrentQueue уже и не нужен.

Вот от 2-го как-нибудь бы избавиться. Суть в том, что возможен вариант, что я достану Job из ConcurrentQueue, но еще не положу её в HashSet, а в этот момент придет еще одна такая же Job, то получу задвоение Job. При добавлении делаются проверки:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
            lock (obj_check_lock)
            {
                if (gisJobsInWork.Contains(new_item))
                    sRet = "Эта БД обрабатывается в данный момент.";
                else if (gisJobsQueue.Contains(new_item))
                    sRet = "Эта БД уже находится в очереди на обработку.";
                else
                {
                    gisJobsQueue.Enqueue(new_item);
                    sRet = "База данных установлена в очередь для обработки сервисом ГИС ЖКХ";
                }
            }
 
            return sRet;
Есть ли какая-нибудь атомарная, потокобезопасная функция перекидывания элемента из одной коллекции в другую?
Текущий вариант:
C#
1
2
3
4
5
6
7
                lock (obj_check_lock)
                {
                    if (gisJobsQueue.TryDequeue(out item))
                    {
                        gisJobsInWork.Add(item);
                    }
                }
Он работает, но я попробовал сделать множество запросов одновременно, внутри 1-го ПК. На 500 одновременных запросах я стал получать ошибки таймаута, которые выдавал TCP сервер на возврат клиенту. Возврат сделан через
C#
1
WriteLineAsync(response).WithCancellation(cts.Token);
где у cts задан таймаут в 10 сек. Т.е. получается вся эта кухня на 500х запросах выполнялась больше 10сек на запрос.

Добавлено через 26 минут
Отбой по вопросу.
Даже не знаю почему, но я взял и перевел Task на Thread c SetApartmentState(ApartmentState.MTA) и 500 запросов отбилось за секунду.
С выводом в консоль, который тоже время отбирает, в дальнейшем планируется запустить Windows Service с логгированием в EventLog.
Пока только концепцию нарабатываю по клиент-серверной архитектуре для всего этого дела. Только сегодня начал службу писать.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
23.11.2018, 17:37
Ответы с готовыми решениями:

Массив из двух очередей
Необходимо создать массив из двух очередей, c=(c0, c1) – массив из двух очередей подскажите как это сделать? У меня есть двусвязный...

Файл из двух очередей
Нужно промоделировать файл с помощью двух очередей. Даже не знаю, с чего начать и как это вообще должно выглядеть.

Задачка на сравнение двух очередей
Собственно условие: Описать функцию, которая проверяет на равенство две очереди. Запутался в самом начале при объявлении struct Quewe...

3
215 / 149 / 48
Регистрация: 28.12.2016
Сообщений: 716
24.11.2018, 06:32
Alex2k17,
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
public class ConcurrentHashSet<T> : IDisposable
    {
        private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
        private readonly HashSet<T> _hashSet = new HashSet<T>();
 
        #region Implementation of ICollection<T> ...ish
        public bool Add(T item)
        {
            _lock.EnterWriteLock();
            try
            {
                return _hashSet.Add(item);
            }
            finally
            {
                if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
            }
        }
 
        public void Clear()
        {
            _lock.EnterWriteLock();
            try
            {
                _hashSet.Clear();
            }
            finally
            {
                if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
            }
        }
 
        public bool Contains(T item)
        {
            _lock.EnterReadLock();
            try
            {
                return _hashSet.Contains(item);
            }
            finally
            {
                if (_lock.IsReadLockHeld) _lock.ExitReadLock();
            }
        }
 
        public bool Remove(T item)
        {
            _lock.EnterWriteLock();
            try
            {
                return _hashSet.Remove(item);
            }
            finally
            {
                if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
            }
        }
 
        public int Count
        {
            get
            {
                _lock.EnterReadLock();
                try
                {
                    return _hashSet.Count;
                }
                finally
                {
                    if (_lock.IsReadLockHeld) _lock.ExitReadLock();
                }
            }
        }
        #endregion
 
        #region Dispose
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
                if (_lock != null)
                    _lock.Dispose();
        }
        ~ConcurrentHashSet()
        {
            Dispose(false);
        }
        #endregion
    }
}
0
1152 / 860 / 263
Регистрация: 30.04.2009
Сообщений: 3,603
24.11.2018, 22:57
Alex2k17, В данном случае lock это вполне нормальное решение.

Цитата Сообщение от Alex2k17 Посмотреть сообщение
в котором крутятся 20 Task и дергают ConcurrentQueue<GisJobItem> на наличие работы.
Чтобы не занимать ресурсы процессора на постоянную проверку наличия задач в очереди лучше добавить AutoResetEvent сигнализирующий о добавлении задачи в очередь.
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
25.11.2018, 05:32
Alex2k17, звучит как типичная задача для Akka Ну или Orleans. Посмотрите, чтобы не переизобретать велосипед, возможно все уже украдено до нас.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
25.11.2018, 05:32
Помогаю со студенческими работами здесь

Стек на базе двух очередей
Мне нужно сделать стек на базе двух очередей, но я не совсем понял как это все устроено, объясните пожалуйста. Стек и очередь по...

Создание двух очередей и стека
Требуется, чтобы программа выполняла обработку нескольких линейных списков (две очереди и стек) в едином адресном пространстве при...

Синхронизация данных в мобильном приложении
Создаю мобильное приложение 1С, нужна помощь в синхронизации. Необходимо реализовать обмен данными мобильного приложения с Розницей в обе...

Составить из элементов двух очередей третью, упорядоченную по невозрастанию
задача: Даны две очереди целых чисел, элементы которых упорядочены по неубыванию. Составить из их элементов третью очередь, упорядоченную...

Определить, в которой из двух очередей больше согласных букв
1)Создать две очереди символов. Входная последовательность символов для обеих оче-редей задается пользователем с клавиатуры. Необходимо: ...


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

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru