![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Выполнение запросов в потоке, с использованием DOA
nobody © (2010-06-21 16:13:00)Вопрос к знатокам:
Почему при выполнении запроса в потоке залипает интерфейс всего приложения, вместо того, чтобы реагировать на действия пользователя во время выполнения запроса?
реализовано в коде следующим образом:
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-модулей.
В каждом модуле есть своя сессия, которая активизируется при необходимости выполнения запроса от этой формы.
Сессия отключается по истечению тайм-аута.
Если нужна еще какая-нить инфа, спрашивайте.
nobody (2010-06-21 17:11:00) [21]
>
> Не знаю, как с 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.
Игорь Шевченко (2010-06-21 17:09:00) [22]Ega23 © (21.06.10 16:57) [25]
Не знаю, как с DOA - не имел дела, а наши компоненты доступа к Oracle вполне спокойно относятся к передаче их в поток (ну и манипуляций с ними в потоке), клиент Oracle - thread safe.
nobody (2010-06-21 17:06:00) [23]
> . Смотри что-то вроде TDAOMemoryTable.
ничего похожего там нету
вот что есть:
TOracleSession, TOracleSessionPool, TOracleQuery, TOracleDataSet, TOraclePackage, TOracleEvent, TOracleQueue, TOracleScript, TOracleDirectPathLoader, TOracleNavigator
nobody (2010-06-21 17:03:00) [24]
> Тяжёлый запрос - это сколько?
от минуты и до часа
Покажите кто-нить кусок кода из готового проекта, плиз!
и примеры вызова, если не трудно... а то все какие-то разговоры об сферическом коне в вакууме и ни строчки кода...(
И как происходит обработка события завершения запроса?
обрабатывать метод OnAfterOpen?
Ega23 (2010-06-21 16:57:00) [25]
> А собственно, в чем проблема ? Это проблема исключительно
> DOA или вообще Оракла ?
Я очень сильно подозреваю, что эта штука лежит у него в ДатаМодуле, на неё куча Датасорсов смотрит и т.д. и т.п.
tesseract (2010-06-21 16:56:00) [26]
> что это за класс такой секретный?
В компонентах от Oracle быть должна. Это просто таблица в памяти. Смотри что-то вроде TDAOMemoryTable.
Ega23 (2010-06-21 16:55:00) [27]
> чтобы тяжелые запросы выполняли в фоне, и у пользера была
> возможность работать с другими формами
Тяжёлый запрос - это сколько?
Игорь Шевченко (2010-06-21 16:54:00) [28]Ega23 © (21.06.10 16:28) [7]
> Только за передачу OracleDataSet в нить я-б руки оторвал.
> По самое нехочу.
А собственно, в чем проблема ? Это проблема исключительно DOA или вообще Оракла ?
nobody (2010-06-21 16:51:00) [29]
> В потоке создаём memtable
что это за класс такой секретный?
nobody (2010-06-21 16:49:00) [30]
> Если честно, я вообще не понимаю, нафига здесь нужен дополнительный
> thread
чтобы тяжелые запросы выполняли в фоне, и у пользера была возможность работать с другими формами
nobody (2010-06-21 16:48:00) [31]
> делаем assign с другим датасетом в synchronize
>
>
> только я бы SendMessage сделал форме, с записью указателя
> на этот мемтейбл в lParam
а в чем разница? все таки assign более понятен при чтении кода...
Ega23 (2010-06-21 16:48:00) [32]Если честно, я вообще не понимаю, нафига здесь нужен дополнительный thread
nobody (2010-06-21 16:47:00) [33]
> Вообще зависит от того как используем поток - из пула или
> создаем / разрушаем под каждый запрос. Создавать/разрушать
> - меньше шанс утечек памяти, пул в разы быстрее.
создаем / разрушаем
tesseract (2010-06-21 16:44:00) [34]
> только я бы SendMessage сделал форме,
Это уже не в общих чертах. С SendMessage конечно эротишнее - у пользователя можно не развивать инфаркт, когда ВНЕЗАПНО у него сбросится весь его ввод - можно предупредить перед началом операции.
Вообще зависит от того как используем поток - из пула или создаем / разрушаем под каждый запрос. Создавать/разрушать - меньше шанс утечек памяти, пул в разы быстрее.
nobody (2010-06-21 16:42:00) [35]
> Опиши проблему для начала. Не в двух словах.
Проблемма: нужно выполнить запрос в потоке, при этом заблокировать контрол(кнопка, экшн, грид), который инициализирует его выполнение, чтобы не порождать два одинаковых потока. И чтобы при этом не блокировалось все приложение целиком.
> В потоке создаём memtable, к нему не надо synchronize. Когда
> он выполнится, делаем assign с другим датасетом в synchronize
> ну или SELECT в него из датасета. Как интереснее.
Можно этот кусочек в исходнике, чтобы было ясно, от чего танцевать.
и вот этот:
> При этом на момент Assign не забываем критсекцией обложить.
Заранее благодарен)
Ega23 (2010-06-21 16:40:00) [36]
> делаем assign с другим датасетом в synchronize
только я бы SendMessage сделал форме, с записью указателя на этот мемтейбл в lParam
nobody (2010-06-21 16:38:00) [37]ух ты! у меня уже слюнки потекли...)))
Ega23 (2010-06-21 16:36:00) [38]
> В потоке создаём memtable, к нему не надо synchronize. Когда
> он выполнится, делаем assign с другим датасетом в synchronize
> ну или SELECT в него из датасета. Как интереснее.
Как вариант.
При этом на момент Assign не забываем критсекцией обложить.
tesseract (2010-06-21 16:35:00) [39]
> или хотя бы в двух словах, как лучше реализовать?
В потокесоздаём memtable, к нему не надо synchronize. Когда он выполнится, делаем assign с другим датасетом в synchronize ну или SELECT в него из датасета. Как интереснее.
Ega23 (2010-06-21 16:34:00) [40]
> а можно глянуть на Вашу реализацию многопоточности в коде
Что именно интересует? Конкретно?
З.Ы. Synchronize там нет. Вообще нет.
> или хотя бы в двух словах, как лучше реализовать?
Опиши проблему для начала. Не в двух словах.