Форум: "Начинающим";
Текущий архив: 2010.09.19;
Скачать: [xml.tar.bz2];
ВнизВыполнение запросов в потоке, с использованием DOA Найти похожие ветки
← →
nobody (2010-06-21 16:13) [0]Вопрос к знатокам:
Почему при выполнении запроса в потоке залипает интерфейс всего приложения, вместо того, чтобы реагировать на действия пользователя во время выполнения запроса?
реализовано в коде следующим образом:
type
TThreadControl = class(TThread)
private
FOracleDataSet: TOracleDataSet;
FOracleQuery: TOracleQuery;
FControl_C: TControl;
FControl_A: TAction;
FGrid: TcxGridDBTableView;
FForm: TForm;
FCollapse: boolean;
FProcessMonitor: TProcessMonitor;
protected
FErrorMsg: string;
procedure Execute; override;
procedure LockControl;
procedure UnLockControl;
procedure ShowErrorMsg;
public
constructor Create(CreateSuspended: Boolean; OracleDataSet: TOracleDataSet;
ProcessMonitor: TProcessMonitor; Control: TControl; Grid: TcxGridDBTableView; Form: TForm; FCollapse: boolean;
LockControl: boolean = true);
overload;
constructor Create(CreateSuspended: Boolean; OracleQuery: TOracleQuery;
ProcessMonitor: TProcessMonitor; Control: TControl; Grid: TcxGridDBTableView; Form: TForm; FCollapse: boolean;
LockControl: boolean = true);
overload;
constructor Create(CreateSuspended: Boolean; OracleDataSet: TOracleDataSet;
ProcessMonitor: TProcessMonitor; Control: TAction; Grid: TcxGridDBTableView; Form: TForm; FCollapse: boolean;
LockControl: boolean = true);
overload;
end;
...
procedure TThreadControl.Execute;
begin
inherited;
try
Synchronize(LockControl);
if FOracleQuery <> nil then
FOracleQuery.Execute;
if FOracleDataSet <> nil then
begin
try
FOracleDataSet.Close;
FOracleDataSet.Open;
except
on E: Exception do
begin
FErrorMsg := E.Message;
Synchronize(ShowErrorMsg);
end;
end;
end;
finally
Synchronize(UnLockControl);
end;
end;
MDI-приложение, дочерние формы загружаются из bpl-модулей.
В каждом модуле есть своя сессия, которая активизируется при необходимости выполнения запроса от этой формы.
Сессия отключается по истечению тайм-аута.
Если нужна еще какая-нить инфа, спрашивайте.
← →
Ega23 © (2010-06-21 16:16) [1]Код LockControl и UnlockControl в студию.
← →
tesseract © (2010-06-21 16:22) [2]
> Почему при выполнении запроса в потоке залипает интерфейс
> всего приложения, вместо того, чтобы реагировать на действия
> пользователя во время выполнения запроса?
Читаем про Synchronize. Он по любому будет выполнятся в контексте основного приложения. Так что рекомендую через memtable SQL выполнять.
← →
nobody (2010-06-21 16:22) [3]
> Код LockControl и UnlockControl в студию.
procedure TThreadControl.LockControl;
begin
FOracleDataSet.DisableControls;
if Assigned(FControl_C) then
FControl_C.Enabled := false;
if Assigned(FControl_A) then
FControl_A.Enabled := false;
if Assigned(FGrid) then
FGrid.BeginUpdate;
if Assigned(FForm) then
FForm.Enabled := false;
end;
procedure TThreadControl.UnLockControl;
begin
FOracleDataSet.EnableControls;
if Assigned(FControl_C) then
FControl_C.Enabled := true;
if Assigned(FControl_A) then
FControl_A.Enabled := true;
if Assigned(FGrid) then
begin
FGrid.EndUpdate;
if FCollapse then
FGrid.ViewData.Collapse(true)
else
FGrid.ViewData.Expand(true);
end;
if Assigned(FForm) then
FForm.Enabled := true;
FProcessMonitor.DelThread(Self.Handle, false);
end;
← →
Ega23 © (2010-06-21 16:24) [4]Какой-то лютый капец.
← →
nobody (2010-06-21 16:25) [5]
> Так что рекомендую через memtable SQL выполнять.
а можно про это попдробней? что это за компонент? tdxMemData подойдет?
← →
nobody (2010-06-21 16:26) [6]
> Какой-то лютый капец.
согласен, это все нужно выбросить. но пока есть только такое
← →
Ega23 © (2010-06-21 16:28) [7]Только за передачу OracleDataSet в нить я-б руки оторвал. По самое нехочу.
← →
nobody (2010-06-21 16:29) [8]если непрозрачно написано по поводу метода синхронизации, то это сделано для того, чтобы , например, по нажатию кнопки, которая вызвала выполнение запроса, нельзя было нажать еще раз, пока данный поток не завершится.
← →
nobody (2010-06-21 16:30) [9]
> Только за передачу OracleDataSet в нить я-б руки оторвал.
> По самое нехочу.
звучит сурово
а можно глянуть на Вашу реализацию многопоточности в коде, или хотя бы в двух словах, как лучше реализовать?
← →
Ega23 © (2010-06-21 16:34) [10]
> а можно глянуть на Вашу реализацию многопоточности в коде
Что именно интересует? Конкретно?
З.Ы. Synchronize там нет. Вообще нет.
> или хотя бы в двух словах, как лучше реализовать?
Опиши проблему для начала. Не в двух словах.
← →
tesseract © (2010-06-21 16:35) [11]
> или хотя бы в двух словах, как лучше реализовать?
В потоке создаём memtable, к нему не надо synchronize. Когда он выполнится, делаем assign с другим датасетом в synchronize ну или SELECT в него из датасета. Как интереснее.
← →
Ega23 © (2010-06-21 16:36) [12]
> В потоке создаём memtable, к нему не надо synchronize. Когда
> он выполнится, делаем assign с другим датасетом в synchronize
> ну или SELECT в него из датасета. Как интереснее.
Как вариант.
При этом на момент Assign не забываем критсекцией обложить.
← →
nobody (2010-06-21 16:38) [13]ух ты! у меня уже слюнки потекли...)))
← →
Ega23 © (2010-06-21 16:40) [14]
> делаем assign с другим датасетом в synchronize
только я бы SendMessage сделал форме, с записью указателя на этот мемтейбл в lParam
← →
nobody (2010-06-21 16:42) [15]
> Опиши проблему для начала. Не в двух словах.
Проблемма: нужно выполнить запрос в потоке, при этом заблокировать контрол(кнопка, экшн, грид), который инициализирует его выполнение, чтобы не порождать два одинаковых потока. И чтобы при этом не блокировалось все приложение целиком.
> В потоке создаём memtable, к нему не надо synchronize. Когда
> он выполнится, делаем assign с другим датасетом в synchronize
> ну или SELECT в него из датасета. Как интереснее.
Можно этот кусочек в исходнике, чтобы было ясно, от чего танцевать.
и вот этот:
> При этом на момент Assign не забываем критсекцией обложить.
Заранее благодарен)
← →
tesseract © (2010-06-21 16:44) [16]
> только я бы SendMessage сделал форме,
Это уже не в общих чертах. С SendMessage конечно эротишнее - у пользователя можно не развивать инфаркт, когда ВНЕЗАПНО у него сбросится весь его ввод - можно предупредить перед началом операции.
Вообще зависит от того как используем поток - из пула или создаем / разрушаем под каждый запрос. Создавать/разрушать - меньше шанс утечек памяти, пул в разы быстрее.
← →
nobody (2010-06-21 16:47) [17]
> Вообще зависит от того как используем поток - из пула или
> создаем / разрушаем под каждый запрос. Создавать/разрушать
> - меньше шанс утечек памяти, пул в разы быстрее.
создаем / разрушаем
← →
Ega23 © (2010-06-21 16:48) [18]Если честно, я вообще не понимаю, нафига здесь нужен дополнительный thread
← →
nobody (2010-06-21 16:48) [19]
> делаем assign с другим датасетом в synchronize
>
>
> только я бы SendMessage сделал форме, с записью указателя
> на этот мемтейбл в lParam
а в чем разница? все таки assign более понятен при чтении кода...
← →
nobody (2010-06-21 16:49) [20]
> Если честно, я вообще не понимаю, нафига здесь нужен дополнительный
> thread
чтобы тяжелые запросы выполняли в фоне, и у пользера была возможность работать с другими формами
← →
nobody (2010-06-21 16:51) [21]
> В потоке создаём memtable
что это за класс такой секретный?
← →
Игорь Шевченко © (2010-06-21 16:54) [22]Ega23 © (21.06.10 16:28) [7]
> Только за передачу OracleDataSet в нить я-б руки оторвал.
> По самое нехочу.
А собственно, в чем проблема ? Это проблема исключительно DOA или вообще Оракла ?
← →
Ega23 © (2010-06-21 16:55) [23]
> чтобы тяжелые запросы выполняли в фоне, и у пользера была
> возможность работать с другими формами
Тяжёлый запрос - это сколько?
← →
tesseract © (2010-06-21 16:56) [24]
> что это за класс такой секретный?
В компонентах от Oracle быть должна. Это просто таблица в памяти. Смотри что-то вроде TDAOMemoryTable.
← →
Ega23 © (2010-06-21 16:57) [25]
> А собственно, в чем проблема ? Это проблема исключительно
> DOA или вообще Оракла ?
Я очень сильно подозреваю, что эта штука лежит у него в ДатаМодуле, на неё куча Датасорсов смотрит и т.д. и т.п.
← →
nobody (2010-06-21 17:03) [26]
> Тяжёлый запрос - это сколько?
от минуты и до часа
Покажите кто-нить кусок кода из готового проекта, плиз!
и примеры вызова, если не трудно... а то все какие-то разговоры об сферическом коне в вакууме и ни строчки кода...(
И как происходит обработка события завершения запроса?
обрабатывать метод OnAfterOpen?
← →
nobody (2010-06-21 17:06) [27]
> . Смотри что-то вроде TDAOMemoryTable.
ничего похожего там нету
вот что есть:
TOracleSession, TOracleSessionPool, TOracleQuery, TOracleDataSet, TOraclePackage, TOracleEvent, TOracleQueue, TOracleScript, TOracleDirectPathLoader, TOracleNavigator
← →
Игорь Шевченко © (2010-06-21 17:09) [28]Ega23 © (21.06.10 16:57) [25]
Не знаю, как с DOA - не имел дела, а наши компоненты доступа к Oracle вполне спокойно относятся к передаче их в поток (ну и манипуляций с ними в потоке), клиент Oracle - thread safe.
← →
nobody (2010-06-21 17:11) [29]
>
> Не знаю, как с DOA - не имел дела, а наши компоненты доступа
> к Oracle вполне спокойно относятся к передаче их в поток
> (ну и манипуляций с ними в потоке), клиент Oracle - thread
> safe.
ДОА тоже поддерживает много поточные приложения
вот цитата из справки:
Multi-threaded applications
In multi-threaded applications, multiple threads might be accessing the database. Sometimes
this is necessary to perform tasks in the background while the user keeps on working with the
application. Multi-threading can also be used to optimize the application"s use of resources of
client, network and server. Finally, multi-threading is necessary if an application needs to be
able to break long running queries on the server.
There are basically two configurations for a multi-threaded application:
Multi-threaded, single -session database access
In this case, multiple threads access one TOracleSession simultaneously. Because the
database server can only handle one request for a specific session at a time, all database
accesses must be serialized. This is achieved by setting the TOracleSession.ThreadSafe
property to true. As a result, all threads block each other when they are accessing the
database. This configuration only makes sense if the threads do a signific ant amount of client
processing relative to the sum of the network and server processing.
Session management needs some special attention in this configuration. The thread that logs
on and off, does transaction control or session control statements, must obviously also be in
control of the other thread(s) to synchronize these actions.
Multi-threaded, multi-session database access
In this case, each thread uses its own dedicated TOracleSession. The client, network and
server can do the processing for these threads parallel, which results in an optimized use of
resources and a non-blocking behavior of the application. No special properties need to be
set, and session management is clear. This is obviously the preferred configuration for a multithreaded
application, but may not always be possible.
For both configurations, access to a TOracleQuery, TOraclePackage and TOracleDataSet
must always be restricted to a single thread.
Any executing query can be aborted by calling the TOracleSession.BreakExecution method.
This causes an "ORA-01013, user requested cancel of current operation"
exception for the currently executing query in that session. Beware that BreakExecution might
not work on all versions of Personal Oracle.
← →
Ega23 © (2010-06-21 17:14) [30]
> Покажите кто-нить кусок кода из готового проекта, плиз!TMyThread = class (TThread)
private
FWND: HWND;
FID: Integer;
function ReportStartExecution: Boolean;
protected
procedure Execute; override;
public
constructor Create(aID: Integer; Wnd: HWND);
procedure DoTerminate; override;
end;
constructor TMyThread.Create(aTaskID: Integer; Wnd: HWND);
begin
inherited Create(True);
FWND := Wnd;
FID := aID;
FreeOnTerminate := True;
end;
function TMyThread.ReportStartExecution: Boolean;
begin
Result := SendMessage(FWND, WM_THREAD_START,
Integer(Self), FID) = WM_RESULT_OK;
end;
procedure TMyThread.DoTerminate;
begin
PostMessage(FWND, WM_THREAD_DONE, Integer(Self), TaskID);
end;
procedure TMyThread.Execute;
begin
try
ReportStartExecution;
//DoSomeWork;
except
//////
end;
end;
← →
nobody (2010-06-21 17:18) [31]
> Ega23 © (21.06.10 17:14) [30]
а соответствующие контроллы блокировать, пока не будет получено сообщение
WM_THREAD_DONE?
← →
Ega23 © (2010-06-21 17:18) [32]
> а наши компоненты доступа к Oracle вполне спокойно относятся
> к передаче их в поток (ну и манипуляций с ними в потоке)
С подключенными DataSource-ами?
Ну тогда это хорошие компоненты.
← →
nobody (2010-06-21 17:19) [33]//DoSomeWork;
- здесь выполнять открытие датасета? а что по поводу memtable? и критических секций по бокам?
← →
Ega23 © (2010-06-21 17:20) [34]
> а соответствующие контроллы блокировать, пока не будет получено
> сообщение
> WM_THREAD_DONE?
Например.
← →
nobody (2010-06-21 17:21) [35]
> С подключенными DataSource-ами?
> Ну тогда это хорошие компоненты.
ДОА тоже нормально работает с подключенными датасорсами в потоке...
← →
nobody (2010-06-21 17:23) [36]
> Например.
Вот я бы тоже и хотел посмотреть на пример использования этой схемы работы с потоком...
← →
Ega23 © (2010-06-21 17:25) [37]
> ДОА тоже нормально работает с подключенными датасорсами
> в потоке...
Дык и обычный какой-нибудь TADODataSet может работать в потоке. С подключенными DataSource. Вопрос в том, как контролы себя вести будут. И насколько это целесообразно.
← →
Игорь Шевченко © (2010-06-21 17:38) [38]Ega23 © (21.06.10 17:18) [32]
> С подключенными DataSource-ами?
> Ну тогда это хорошие компоненты.
Ты не путай божий дар с яичницей. Если у тебя в потоке происходит DataEvent и подключены визуальные компоненты, то все, что пишется в комментариях к TThread про Syncronize, остается в силе. А сами DataSet-ы в потоках вполне могут осуществлять свою функциональность. Например, их можно обходить.
← →
nobody (2010-06-21 18:09) [39]кстати, убрал из метода TThreadControl.Execute
LockControl и UnLockControl и вроде перестало так залипать, но пока непонятно, где лочить контролы, во время выполнения потока ... или сделать это до выполнеия запроса, прямо перед созданием потока?... тогда нужен флаг, который будет сигнализировать завершение потока...
вообщем туманно все и конкретных примеров с критической секцией никто не привел... а как все хорошо начиналось... эх, пойду-нажрусь с горя!
← →
Ega23 © (2010-06-21 18:10) [40]
> вообщем туманно все и конкретных примеров с критической
> секцией никто не привел
Гугл, Demos и книжки - как, отменили?
Страницы: 1 2 вся ветка
Форум: "Начинающим";
Текущий архив: 2010.09.19;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.006 c