TOraDataSet блокирует мою программу, даже если для NonBlocking установлено значение true
Я пытался сделать небольшой экран-заставку, чтобы моя программа могла открывать запросы без блокировки моего приложения. Код, который я написал это.
procedure TOpenThread.OpenTable;
begin
FActiveTable.NonBlocking := true;
FActiveTable.open;
end;
procedure TOpenThread.AbrirTablas;
begin
FActiveTable := FOwnerPlan.TablasEdicion.Tabla;
Synchronize(OpenTable);
while FActiveTable.Executing do
begin
if Terminated then CancelExecution;
sleep(10);
end;
FActiveTable.NonBlocking := false;
end;
Этот код выполняется в потоке, и продолжает делать это, пока основной поток застревает
Я пользуюсь delphi 2007
1 ответ
Этот код выполняется в потоке
Теперь это не так. Ваш код:
Synchronize(OpenTable);
Это явно означает OpenTable
процедура выполняется внутри основного потока VCL и вне вашего вспомогательного фона TOpenThread
,
Подробнее о Synchronize
Вы можете попытаться извлечь уроки по адресу /questions/38293747/kak-pravilno-realizovat-temyi-dlya-risovaniya-na-holste/38293751#38293751
В общем, просто нет простых решений сложных проблем.
Если вы хотите разгрузить взаимодействия с БД в отдельный поток, вы должны сделать этот поток эксклюзивным владельцем и пользователем всех компонентов БД, начиная с самого соединения с БД и вплоть до каждой транзакции и каждого запроса.
Тогда вам нужно будет сделать средства, чтобы АСИНХРОНОЛЬНО отправлять запросы данных из основного потока VCL в поток вспомогательных БД, и АСИНХРОНОЛЬНО получать пакеты данных от него. Нечто подобное OmniThreadLibrary делает с потоками данных - прочитайте их руководства, чтобы получить представление о внутренней структуре программы при использовании многопоточности.
Вы можете попробовать изменить ваше приложение в соответствии со следующими практическими правилами. Это будет не самая быстрая многопоточность, но, возможно, самая простая.
все компоненты базы данных работают исключительно внутри
TOpenThread.Execute
контекст и эти компоненты являются локальными переменными членамиTOpenThread
учебный класс. Подключение-отключение производится только в пределахTOpenThread.Execute
;TOpenThread.Execute
ждет команд из основного потока в почти бесконечном (до тех пор, пока поток не завершится) и дросселированном цикле.конкретные запросы к базе данных делаются как
anonymous procedures
и добавляются к некоторымTThreadedQueue<T>
публичный членTOpenThread
объект. Петля внутри.Execute
пытается извлечь действие из этой очереди и выполнить его, если таковое существует, или ограничить (Yield()
) если очередь была пуста. ниSynchronize
ниQueue
Обертки разрешены вокруг операций с базой данных. Основной поток VCL только отправляет запросы, но НИКОГДА не ожидает их фактического выполнения.эти анонимные процедуры после выполнения передают результаты базы данных обратно в основной поток. Как http://www.uweraabe.de/Blog/2011/01/30/synchronize-and-queue-with-parameters/ или как Отправка данных из TThread в основной поток VCL или любым другим обратно в основной поток путь.
TOpenThread.Execute
выходит из цикла, только еслиTerminated
флаг установлен и очередь пуста. ЕслиTerminated
устанавливается, то немедленный выход потеряет действия, все еще ожидающие в очереди без обработки.
Кажется скучным и утомительным, но легко? Вовсе нет, добавьте, что вам придется перехватывать исключения и обрабатывать все ошибки в асинхронном режиме - и вы "потеряете надежду, попав в эту область".
PS. и последнее, но не менее важное: "Этот код выполняется в потоке и продолжает делать это, пока основной поток застревает". Предположим, честно говоря, я полагаю, что вы здесь не правы, и я думаю, что ОБА ваши потоки застряли друг в друге, Без полного понимания того, как межпотоковая блокировка предназначена для работы в этом конкретном компоненте, код бомбардировки ковров с вызовами Synchronize
и другие инструменты блокировки между потоками, у вас есть шанс просто погнать их все свои потоки в состояние взаимной блокировки, взаимоблокировки. См. /questions/15025494/chto-takoe-tupik