Синхронизация потоков

tarakan19832

Member
Joined
month_8_short 12, 2016
Messages
6
Reaction score
0
Подскажите, пожалуйста, на моем примере как правильно синхронизировать несколько потоков.
На форме есть n количество combobox, каждый заполняется из разных таблиц БД.
Я делал так
1. Выключаю первый combobox. ( synchronize(comboboxN.enable = false) )
2. В Execute создаю TstringList и заполняю его данными из таблицы N, т.е. while not tableN.eof do TstringListN.add(tableN.poleN)
3. Потом synchronize (comboboxN.items := TstringListN)
4. И включаю ComboboxN ( synchronize(comboboxN.enable = false) )
Так я проделываю со всеми Combobox по очереди, а хочется запустить несколько потоков, заполнить все Combobox и по окончании включить сразу все. Т.е. я понимаю так, что должен быть поток, который бы запускал все остальные и проверял : все законченно или нет. Если все потоки отработали, то включил все combobox’ы. Подскажите как это осуществить?
 

isam_os

New member
Joined
month_8_short 27, 2016
Messages
3
Reaction score
0
попробуй создать на каждый комбо , отдельный поток ? или у тебя там их мильён ?
 

LeshaRB

Premium Member
VIP
Joined
month_6_short 11, 2022
Messages
322
Reaction score
451
Location
Canada
Deposit
$ 150
Как выполнить N операций M потоками, как-то так я бы гуглил
 

dustypup

Member
Joined
month_11_short 27, 2008
Messages
21
Reaction score
1
Создай несколько экземпляров потока.
Передай в каждый поток указатель на свой комбобокс.
В потоке заполняй комбобокс и enable его.
Запускай все потоки одновременно.
 

fets

Member
Joined
month_10_short 4, 2011
Messages
7
Reaction score
1
synchronize используется для GUI, для синхронизации действий, лучше использовать симофоры, пока действие не будет сделано семафор дальше не пустит:

SemaphoreTask : THandle;
.....
SemaphoreTask := CreateSemaphore(nil, 0, 2147483647, '');
.....

// Эта команда WaitForSingleObjectEx будет ожидать с любого участка программы --> ReleaseSemaphore(SemaphoreTask, 1, nil);
WaitForSingleObjectEx(SemaphoreTask , INFINITE, True);
....
// закрыть семафор
CloseHandle(SemaphoreTask );

Таким образом можешь синхронизировать любый задачи!
 

tarakan1983

Member
Joined
month_7_short 30, 2016
Messages
8
Reaction score
0
Есть такое простое слово как mutex - оно все объясняет.

Я понимаю, Вы профессионал и это слово Вам все объяснят, но мне не очень. Не могли бы Вы вкратце с примерчиком? Или дайте ссылку на пример.
 

Earl_Vadim

Member
Joined
month_8_short 1, 2015
Messages
7
Reaction score
1
Нет. я не профессионал.. все сам ищу через поиск.
Суть mutex - тотже симафор... просто поиском вы больше инфы найдете по слову mutex, чем по слову Semaphore ..

а вообще более полного и более правильного описания потоков чем это

You need to log in to view the content.


вы не найдете.
 

alchemist131

Premium Member
Joined
month_11_short 16, 2020
Messages
116
Reaction score
34
По вопросам синхронизации фундаментальный труд - Джеффри РИХТЕР "Создание эффективных WIN32-приложений с учётом специфики 64-разрядной версии Windows". В нем описаны все основные элементы WinAPI и особенности их использования (семафоры, мьютексы в том числе). Переложить на Delphi труда не составит.
В описанной задаче в потоке-синхронизаторе, на мой взгляд, необходимости нет. Каждый поток может независимо от другого заполнять TStringList из базы. Дальнейший перенос в TComboBox осуществляется с помощью Synchronize. Этот метод сам по себе не даст другим потокам обратиться к основному потоку Vcl, пока какой-либо пишет данные в TComboBox.
 

Keoda

Member
Joined
month_11_short 19, 2014
Messages
31
Reaction score
25
Если у тебя доступ к базе данных на чтение открыт свободно, я бы сделал потоки для каждого комбобокса:
hThr = CreateThread(NULL, 0, ThreadProcName, pCombobox, 0, &dwThrID);
В потоке читал бы базу и обновлял содержимое формы.
Если хочешь включить сразу все комбобоксы пусть каждый поток выставит Event по окончании работы, а основной поток пусть ждёт все эти Events через WaitforMultipleObjects. только я настоятельно рекомендую не писать INFINITE, чтобы не вешать поток, лучше взять заведомо большее время, за которое точно должны сработать потоки (60000 мс например).
DWORD rez = WaitforMultipleObjects(iCheckBoxNumber, evThreadHadDoneItsWork, TRUE, 60000);
if(rez == WAIT_TIMEOUT)
{
// Ждали минуту потоки не завершились
}
else if (rez == WAIT_OBJECT_0) {включить все комбы}
 
Last edited by a moderator:

robt

New member
Joined
month_4_short 29, 2015
Messages
2
Reaction score
0
это все многопоточная чушь
в итоге со всеми синхронизациями и прочей фигней результат будет тот же, что и без потоков + куча лаганого ненужного говнокода
выключил все сразу, заполнил и включил
 

Kelvin21

Member
Joined
month_10_short 6, 2016
Messages
11
Reaction score
0
Эм, а разве нельзя использовать критические секции? Всегда ими пользовался когда нужно обратиться к форме. Либо использовать глобальные массивы по окончанию работы из которых заполнять форму. или по таймеру например. Ведь куча вариантов.
 

ForumReader

Member
Joined
month_10_short 16, 2008
Messages
8
Reaction score
4
Вообще, множественная работа с GUI в потоках - тот еще геморрой, соглашусь с комментатором №11
 

protos59

Member
Joined
month_9_short 15, 2016
Messages
6
Reaction score
0
VCL, насколько я понимаю, однопоточный и из разных потоков в данной задаче работать с ним смысла наверное нат. Заполняться они наверняка будут по-очереди.

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

styxozavr

Member
Joined
month_7_short 25, 2009
Messages
11
Reaction score
68
Многие DAC позволяют получать данные из БД в потоках параллельно, нужно только каждому запросу предоставить отдельный коннекшн. Никаких проблем не наблюдал.
 
Last edited by a moderator:

Mollieswp

GOLD
Premium
Joined
month_5_short 30, 2023
Messages
120
Reaction score
23
нужно только каждому запросу предоставить отдельный коннекшн
очень смешно
это кто додумался до такого?

для многопоточных запросов нужно в самом query выставить тип Asynchrone
или в одном подключении запустить многопоточный TTHeread

1 connection - 1 запрос это очень не то
 

styxozavr

Member
Joined
month_7_short 25, 2009
Messages
11
Reaction score
68
это кто додумался до такого?

цитата из мануала FireDAC said:
A connection object and all objects associated with it (such as TFDQuery, TFDTransaction, and so on) are used by a single thread at each moment.
Иными словами: для того, чтоб запросы работали асинхронно, необходимо каждому предоставить свой коннект.
 

protos59

Member
Joined
month_9_short 15, 2016
Messages
6
Reaction score
0
очень смешно
это кто додумался до такого?

для многопоточных запросов нужно в самом query выставить тип Asynchrone
или в одном подключении запустить многопоточный TTHeread

1 connection - 1 запрос это очень не то

А что не так? Речь идет о параллельном выполнении. Известные мне СУБД не умеют через одно соединение выполнять одновременно несколько запросов. Со стороны delphi можно использовать пул соединений, который скроет создание нескольких соединений.
 

Zhrnya

Member
Joined
month_5_short 6, 2010
Messages
7
Reaction score
0
обявляешь
CRITICAL_SECTION _USEVCL;

..................
..................
инициализируешь
InitializeCriticalSection(&_USEVCL);


потом пользуешься в каждом потоке. Обрамляешь конкурирующие действия в EnterCriticalSection и LeaveCriticalSection.

EnterCriticalSection(&__USEVCL);
критичные код
LeaveCriticalSection(&__USEVCL);

тут главное не забывать делать leave.
 
Top