Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2006.03.19;
Скачать: [xml.tar.bz2];

Вниз

Отображение длительных процессов   Найти похожие ветки 

 
BanderLog   (2006-02-13 10:45) [0]

Привет мастерам!
Необходимо в программе при выполнении длительной операции показывать окно с какой либо надписью, вроде "Идет обработка вышего запроса". При этом основное окно не должно быть доступно. К тому же необходимо иметь на этой форме кнопочку "Отмена" (опционально), для отмены операции.
Подскажите в какую сторону смотреть и как лучше подобное реализовать?


 
Marser ©   (2006-02-13 10:46) [1]

Application.ProcessMessages


 
BanderLog   (2006-02-13 10:51) [2]

И куда его писать? :)


 
ЮЮ ©   (2006-02-13 10:57) [3]

В тот цикл, который мещает нажать кнопкку "отмена" и перерисовывть форму. А в кнопке отмена надо сделать такие дейтствия, чтобы когда прожолжится выполнение цикла стало ясно, что следкет прервать цикл.


 
BanderLog   (2006-02-13 11:04) [4]

А если длительная операция это выполнение SQL запроса?


 
Digitman ©   (2006-02-13 11:06) [5]


> BanderLog   (13.02.06 11:04) [4]


СУБД какая ?


 
BanderLog   (2006-02-13 11:10) [6]

FireBird, но прерывать SQL запрос не надо :) Необходимо просто показать сообщение что он выполняется и основную форму закрыть для доступа.


 
ЮЮ ©   (2006-02-13 11:11) [7]

Тогда лучше оптимизировать запрос :)
Или выполнять его в отдельном Thread-е с убитием последнего.
Или выполнять в асинхронном режиме с убитием, наверное, компонента или вызовов надлежащего метода.


 
Digitman ©   (2006-02-13 11:12) [8]


> BanderLog   (13.02.06 11:10) [6]


Запусти запрос на выполнение в доп.потоке.
А в основном потоке покажи юзеру какой-нть прогресс был или анимацию, создающие иллюзию "бурной деятельности" твоей программы


 
Maverick ©   (2006-02-13 11:23) [9]

для примера, вот нашел...как по простому вызвать процедуру в доп.потоке

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls;

procedure incedit1; stdcall;
procedure incedit2; stdcall;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Edit1: TEdit;
   Edit2: TEdit;
   Button6: TButton;
   Button7: TButton;
   Button2: TButton;
   Button3: TButton;
   Button5: TButton;
   Button4: TButton;
   procedure Button1Click(Sender: TObject);
   procedure Button6Click(Sender: TObject);
   procedure Button7Click(Sender: TObject);
   procedure Button4Click(Sender: TObject);
   procedure Button5Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
   procedure Button3Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

var
 th1, th2: cardinal;
 h1, h2: integer;

procedure incedit1;
var
 i: integer;
begin
 i := 0;
 while true do
 begin
   form1.edit1.text := inttostr(i);
   i := i + 1;
 end;
end;

procedure incedit2;
var
 i: integer;
begin
 i := 0;
 while true do
 begin
   form1.edit2.text := inttostr(i);
   i := i + 1;
 end;
end;
{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
 h1 := beginthread(nil, 1024, @incedit1, nil, 0, th1);
 h2 := beginthread(nil, 1024, @incedit2, nil, 0, th2);
end;

procedure TForm1.Button6Click(Sender: TObject);
begin
 terminatethread(h1, 0);
end;

procedure TForm1.Button7Click(Sender: TObject);
begin
 terminatethread(h2, 0);
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
 resumethread(h1);
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
 resumethread(h2);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 suspendthread(h1);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
 suspendthread(h2);
end;

end.


 
Digitman ©   (2006-02-13 11:27) [10]


> Maverick ©   (13.02.06 11:23) [9]
> для примера, вот нашел...как по простому вызвать процедуру
> в доп.потоке


Выкинь этот пример в мусор.
В нем - грубые ошибки.


 
Maverick ©   (2006-02-13 11:30) [11]

> Digitman ©   (13.02.06 11:27) [10]
>Выкинь этот пример в мусор.
>В нем - грубые ошибки.

поясни, плз...
(я сам тока учусь :)  )


 
BanderLog   (2006-02-13 11:35) [12]

Достаточно показать пользователю сообщение и заблокировать основную форму, так как покуда не будут найдены необходимые данные пользователю и программа не нужна... показывать такое сообщение надо будет не только при выполнении запроса, но и при пакетной обработке файлов другим приложением которое запускается через CreateProcess и WaitForSingleObject, которую и нужно будет отменять.


 
Digitman ©   (2006-02-13 11:57) [13]

1. incedit д.б. объявлена так:

function incedit(Parameter: Pointer): Integer;

2. Обращения к визуальным vcl-контролам в контексте до.потока vcl-приложения недопустимы


> BanderLog   (13.02.06 11:35) [12]


Ну и покажи это средствами Form.ShowModal !
В чем проблема-то ?


 
Maverick ©   (2006-02-13 12:13) [14]

>Digitman ©   (13.02.06 11:57) [13]

согласен, каюсь, выдернул от куда то пример, толком его не просмотрев :)
я хотел просто показать человеку возможный подход..а в теле процедуры incedit можно отписать sql запрос...


 
BanderLog   (2006-02-16 13:57) [15]


> Digitman ©   (13.02.06 11:57) [13]
> Ну и покажи это средствами Form.ShowModal !
> В чем проблема-то ?

ShowModal заморозит основной процесс пока не юудет закрыто окно, чем мне это поможет?

Вопрос, внутри потока можно создать форму, которая будет работать в этом потоке и при его завершениии будет уничтожаться? Эта форма никак не должна взаимодействовать с главной. (допустим, нажал в главной программе кнопку - запустился поток, который создал форму с обычным лебел, который отображает текущее время, надоело это окно пользователю, выключил его)


 
Игорь Шевченко ©   (2006-02-16 14:06) [16]

Не надо в доп. потоке запрос выполнять, надо в доп. потоке форму для пользователя показывать


 
BanderLog   (2006-02-16 14:14) [17]

Подскажите как это сделать, пожалуйста.


 
Digitman ©   (2006-02-16 14:28) [18]


> BanderLog   (16.02.06 13:57) [15]


А теперь -  внятно..


 
Defunct ©   (2006-02-16 15:16) [19]

Игорь Шевченко ©   (16.02.06 14:06) [16]

Имелось в виду наоборот?


 
Игорь Шевченко ©   (2006-02-16 16:09) [20]

Defunct ©   (16.02.06 15:16) [19]

Имелся в виду аналог стандартной анимации Windows, где действия (например, по копированию больших файлов) выполняются в основном потоке, а обновление изображения на заставке при копировании в проводнике - в дополнительном.


 
BanderLog   (2006-02-17 12:59) [21]


> Digitman ©   (16.02.06 14:28) [18]
> А теперь -  внятно..


SplashForm.ShowModal;
SQL.Open;

Когда у меня начнется начнется открываться запрос?
Может Вас смутило слово "заморозит", то согласен, некорректная формулировка, но смысл ясен, код продожиться выполняться только после того как модальное окно будет закрыть. (или может я чего то не понимаю в данном случае)


> Игорь Шевченко ©   (16.02.06 16:09) [20]
> Defunct ©   (16.02.06 15:16) [19]
>
> Имелся в виду аналог стандартной анимации Windows, где действия
> (например, по копированию больших файлов) выполняются в
> основном потоке, а обновление изображения на заставке при
> копировании в проводнике - в дополнительном.


Абсолютно верно. Хочется узнать о возможных путях реализации данного варианта.


 
Mikhail   (2006-02-17 14:37) [22]


procedure TForm1.Button1Click(Sender: TObject);
var
 i: Integer;
begin
 T := TSQThread.Create;
 Sleep(1000);
 SQL.Open;
end;

...

procedure TSQThread.Execute;
begin
 TForm2.Create(nil).ShowModal;
end;


 
Fay ©   (2006-02-17 14:39) [23]

2 Mikhail   (17.02.06 14:37) [22]
Что это было?


 
Mikhail   (2006-02-17 15:40) [24]


> Fay ©   (17.02.06 14:39) [23]

Для интереса попробовал. А это кусочек, возможно не очень вразумительный.


 
Игорь Шевченко ©   (2006-02-17 15:55) [25]

BanderLog   (17.02.06 12:59) [21]


> Абсолютно верно. Хочется узнать о возможных путях реализации
> данного варианта.


Канва примерно такая (писано на скорую руки, возможны ошибки). Долгое действие имитировалось таймером.

unit main;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 ExtCtrls, StdCtrls, ProgressThread;

type
 TfMain = class(TForm)
   Button: TButton;
   Timer: TTimer;
   procedure ButtonClick(Sender: TObject);
   procedure TimerTimer(Sender: TObject);
 private
   FProgressThread: TProgressThread;
   procedure LongProcessStarted;
   procedure LongProcessCompleted;
 end;

var
 fMain: TfMain;

implementation

{$R *.DFM}

procedure TfMain.ButtonClick(Sender: TObject);
begin
 LongProcessStarted;
 Timer.Enabled := true;
end;

procedure TfMain.LongProcessCompleted;
begin
 FProgressThread.Terminate;
 FProgressThread.WaitFor;
 FProgressThread.Free;
end;

procedure TfMain.LongProcessStarted;
begin
 FProgressThread := TProgressThread.Create (Self);
end;

procedure TfMain.TimerTimer(Sender: TObject);
begin
 LongProcessCompleted;
end;

end.


unit ProgressThread;

interface

uses
 Windows, Forms, Classes;

type
 TProgressThread = class(TThread)
 private
   FParentWidth, FParentHeight: Integer;
   FWindow: HWND;
   FParentWindow: HWND;
   function InitProgressThread: Boolean;
 protected
   procedure Execute; override;
 public
   constructor Create (ParentForm: TForm);
   destructor Destroy; override;
 end;

implementation
uses
 SysUtils, Messages;

function ThreadWndProc (Wnd: HWND; Message: UINT; wParam: WPARAM;
 lParam: LPARAM): LRESULT; stdcall;
var
 ps: PAINTSTRUCT;
 rctext: TRect;
begin
 case Message of
 WM_TIMER:
   begin
     if wParam = 1000 then begin
       InvalidateRect (Wnd, nil, false);
       Result := 0;
     end else
       Result := DefWindowProc (Wnd, Message, wParam, lParam);
   end;
 WM_DESTROY:
   begin
     KillTimer(Wnd, 1000);
     PostQuitMessage(0);
     Result := 0;
   end;
 WM_PAINT:
   begin
     BeginPaint(Wnd, ps);
     SetTextColor(ps.hdc, 0);
     GetClientRect(Wnd, rctext);
     DrawText (ps.hdc, PChar(Format("running %d", [GetTickCount])), -1,
       rctext, DT_CENTER or DT_VCENTER);
     EndPaint(Wnd, ps);
     Result := 0;
   end;
 else
   Result := DefWindowProc (Wnd, Message, wParam, lParam);
 end;
end;

function TProgressThread.InitProgressThread: Boolean;
const
 Height = 100;
 Width = 200;
var
 wc: WNDCLASS;
begin
 FillChar (wc, SizeOf(wc), 0);
 wc.lpfnWndProc := @ThreadWndProc;
 wc.lpszClassName := "HSProgressWindowClass";
 wc.hInstance := HInstance;
 wc.hbrBackground := GetStockObject(WHITE_BRUSH);
 Result := Windows.RegisterClass(wc) <> 0;
 if not Result then
   Exit;
 FWindow := CreateWindowEx (0, "HSProgressWindowClass", "ProgressWindow",
   WS_CHILD or WS_VISIBLE or WS_BORDER, (FParentWidth - Width) div 2,
     (FParentHeight - Height) div 2, Width, Height, FParentWindow, 1,
     HInstance, Self);
 Result := IsWindow(FWindow);
 if not Result then
   Exit;
 SetTimer(FWindow, 1000, 500, nil);
 UpdateWindow(FWindow);
end;

{ TProgressThread }

constructor TProgressThread.Create(ParentForm: TForm);
begin
 FreeOnTerminate := false;
 FParentWidth := ParentForm.Width;
 FParentHeight := ParentForm.Height;
 FParentWindow := ParentForm.Handle;
 inherited Create (false);
end;

procedure TProgressThread.Execute;
var
 Msg: TMsg;
begin
 if not InitProgressThread then
   Exit;
 while GetMessage(Msg, FWindow, 0, 0) and not Terminated do begin
   TranslateMessage(Msg);
   DispatchMessage(Msg);
 end;
 if Terminated then
   DestroyWindow(FWindow);
end;

destructor TProgressThread.Destroy;
begin
 Windows.UnregisterClass("HSProgressWindowClass", HInstance);
 inherited;
end;

end.


 
Defunct ©   (2006-02-17 19:11) [26]


> Игорь Шевченко ©   (16.02.06 16:09) [20]
> Defunct ©   (16.02.06 15:16) [19]
>
> Имелся в виду аналог стандартной анимации Windows, где действия
> (например, по копированию больших файлов) выполняются в
> основном потоке, а обновление изображения на заставке при
> копировании в проводнике - в дополнительном.


А чем такой способ лучше обратного (анимация в основном, действия в доп. потоке)?
Просто в свете ограничений связанных с VCL впервые слышу о подобном способе реализации анимации.


 
Игорь Шевченко ©   (2006-02-17 20:54) [27]

Defunct ©   (17.02.06 19:11) [26]

Тем, что иногда перенос дополнительных действий в другой поток ведет к неоправданным затратам. Например, для того, чтобы выполнить запрос к базе данных в отдельном потоке, часто необходимо создать новое подключение к ней.

Все зависит от задачи, как всегда.


> Просто в свете ограничений связанных с VCL впервые слышу
> о подобном способе реализации анимации.


MS вроде документирует этот способ. По таймеру показывается последовательность картинок при анимации.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2006.03.19;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.53 MB
Время: 0.014 c
15-1140631011
DSKalugin
2006-02-22 20:56
2006.03.19
Microsoft Internet Explorer вне закона, как обычно


2-1141194386
StelS
2006-03-01 09:26
2006.03.19
Справка


3-1138283474
ivc_andr
2006-01-26 16:51
2006.03.19
не отправляются письма через SQL Mail и Outlook 2003


2-1141121527
sanich
2006-02-28 13:12
2006.03.19
Поиск подстроки


2-1141048509
49 Cent
2006-02-27 16:55
2006.03.19
Какой компонент поможет отобразить график?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский