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

tarakan19832

Member
Joined
Aug 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
Aug 27, 2016
Messages
3
Reaction score
0
попробуй создать на каждый комбо , отдельный поток ? или у тебя там их мильён ?
 

LeshaRB

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

dustypup

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

fets

Member
Joined
Oct 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 );

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

Earl_Vadim

Member
Joined
Aug 1, 2015
Messages
7
Reaction score
1
Есть такое простое слово как mutex - оно все объясняет.
 

tarakan1983

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

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

Earl_Vadim

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

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

You need to log in to view the content.


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

alchemist131

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

Keoda

Member
Joined
Nov 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
Apr 29, 2015
Messages
2
Reaction score
0
это все многопоточная чушь
в итоге со всеми синхронизациями и прочей фигней результат будет тот же, что и без потоков + куча лаганого ненужного говнокода
выключил все сразу, заполнил и включил
 

Kelvin21

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

ForumReader

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

protos59

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

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

styxozavr

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

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

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

styxozavr

Member
Joined
Jul 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
Sep 15, 2016
Messages
6
Reaction score
0
очень смешно
это кто додумался до такого?

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

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

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

Zhrnya

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

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


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

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

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