Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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.005 c
15-1277099793
12
2010-06-21 09:56
2010.09.19
Ошибка AV на строке TRY. Что за ерунда?


2-1277317567
lihoy_p5
2010-06-23 22:26
2010.09.19
загрузка следующего изображения


15-1276971762
sniknik
2010-06-19 22:22
2010.09.19
Перехват ссылки в TWebBrowser.


15-1277095834
И. Павел
2010-06-21 08:50
2010.09.19
Странное переполнение


15-1277274873
pasha_golub
2010-06-23 10:34
2010.09.19
PHP: когда закрывать соединение с базой





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский