/ Forside / Teknologi / Udvikling / Delphi/Pascal / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
Delphi/Pascal
#NavnPoint
oldwiking 603
jrossing 525
rpje 520
EXTERMINA.. 500
gandalf 460
gubi 270
DJ_Puden 250
PARKENSS 230
technet 210
10  jdjespers.. 200
Tråde, Delphi 5 div. småspørgsmål
Fra : Michael Vilhelmsen


Dato : 21-12-05 20:45

Hej

Jeg er ved at prøve at lave en rutine i en tråd.
Ret banalt set, skal der ske det, at når tråden aktiveres, skal et
vindue komme op med en progress bar, som stille og roligt bevæger sig
ud til enden, for så at starte forfra.
Dette lige indtil jeg terminerer tråden.

Jeg har pt. lave en ganske lille test appl. som består af:

1.
Min hovedform.
unit Pg1;

interface

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


type
TForm1 = class(TForm)
Button1: TButton;
Bevel1: TBevel;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
MyThread1 : TMyThread; // thread number 1
Thread1Active : boolean; // used to test if thread 1 is active
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject); // Create Thread 1
begin
if (MyThread1 = nil) or (Thread1Active = false) then // make sure
its not already running
begin
MyThread1 := TMyThread.CreateIt;
Thread1Active := true;
end
else
ShowMessage('Thread still executing');
end;

procedure TForm1.Button3Click(Sender: TObject); // Terminate Thread 1
begin
if (MyThread1 <> nil) and (Thread1Active = true) then // check to
see if it is running
begin
MyThread1.Terminate;
end
else
ShowMessage('Thread not started');
end;



procedure TForm1.FormCreate(Sender: TObject); // initialize to zero
begin
Thread1Active := false;
end;



end.


Dette er bare en form med 2 knapper.
Den ene skulle gerne starte tråden, den anden afslutte den.




2.
Tråden:
unit Pg2;

interface

uses
Classes, comctrls;

type
TMyThread = class(TThread)
private
protected
procedure Execute; override; // Main thread execution
published
constructor CreateIt;
destructor Destroy; override;
procedure ss;
end;

implementation

uses
windows, UVent2;

constructor TMyThread.CreateIt;
begin
inherited Create(true); // Create thread suspended
FreeOnTerminate := true; // Thread Free Itself when terminated
Suspended := false; // Continue the thread
frmVent2 := TfrmVent2.Create(nil);
end;

destructor TMyThread.Destroy;
begin
frmVent2.Release;
inherited destroy;
end;

procedure TMyThread.ss;
begin
frmVent2.Close;
end;

procedure TMyThread.Execute; // Main execution for thread
begin
frmVent2.ShowModal;
end;



end.


Som det ses, henviser den til en form, som har 2 paneller på og en
progressbar og en timer.
Timeren kører hvert 200 ms, og "flytter" progressbaren.
Selve koden under ser sådan ud:

unit UVent2;

interface

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

type
TfrmVent2 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
Panel3: TPanel;
pBar: TProgressBar;
ti: TTimer;
procedure FormShow(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure tiTimer(Sender: TObject);
procedure FormHide(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
frmVent2: TfrmVent2;

implementation



var
Teller : INteger;
{$R *.DFM}

procedure TfrmVent2.FormShow(Sender: TObject);
begin
Teller := 1;
pBar.Max := 500;
pBar.Min := 0;
pBar.Position := 0;
ti.Enabled := TRUE;
Panel1.Update;
Panel2.Update;
self.Update;
end;

procedure TfrmVent2.FormCreate(Sender: TObject);
begin
ti.Enabled := FALSE;
end;


procedure TfrmVent2.tiTimer(Sender: TObject);
begin
INC(Teller);
if (Teller>pBar.Max) then
Teller := 0;
pBar.Position := Teller;
self.Update;
end;

procedure TfrmVent2.FormHide(Sender: TObject);
begin
ti.Enabled := FALSE;
end;

end.



Alt i alt, kan jeg få formen til at komme frem.
Progressbaren flytter sig stille og roligt, og når den når enden,
starter den forfra.

MEN - når jeg vil terminate tråden,sker der intet.

Jeg kan så lukke programmet, og det er så det.

Jeg har prøvet at ændre frmvent2.showmodal til frmvent2.show, men så
terminere tråden med det samme med en fejl.

Jeg kan ikke rigtig finde ud af, hvor jeg gør det forkert henne.

Hvis nogen skulle lige inde med et lille eksempel på en program, som
kan vise en form via en tråd, og afslutte den igen, vil jeg da gerne se
det....
Gerne på mail..

Michael



--
This is an automatic signature of MesNews.
Site : http://mesnews.no-ip.com




---
avast! Antivirus: Outbound message clean.
Virus Database (VPS): 0551-2, 20-12-2005
Tested on: 21-12-2005 20:44:52
avast! - copyright (c) 1988-2005 ALWIL Software.
http://www.avast.com




 
 
Hans (22-12-2005)
Kommentar
Fra : Hans


Dato : 22-12-05 09:28


"Michael Vilhelmsen" <Mivi_FJERN@FJERN_Hunderupnet.dk> skrev i en meddelelse
news:mn.acdc7d5c4055c8c1.11891@FJERNHunderupnet.dk...
> Hej
>
> Jeg er ved at prøve at lave en rutine i en tråd.
> Ret banalt set, skal der ske det, at når tråden aktiveres, skal et vindue
> komme op med en progress bar, som stille og roligt bevæger sig ud til
> enden, for så at starte forfra.
> Dette lige indtil jeg terminerer tråden.

<klip en masse>

Hvorfor bruger du en tråd til at kalde ShowModal, hvorfor ikke bare kalde
Show fra din hovedform og glemme alt om en tråd.
Men ellers kan du ikke afslutte din tråd med Terminate fordi du ikke checker
i Execute om tråden skal afslutte, en tråds Execute metode skal ligne nogen
i denne stil:

procedure TMyThread.Execute; // Main execution for thread
begin
while not terminated do
begin
//noget kode, evt. en sleep
end;
end;

/HK



Michael Vilhelmsen (22-12-2005)
Kommentar
Fra : Michael Vilhelmsen


Dato : 22-12-05 11:26

Hans explained on 22-12-2005 :
> "Michael Vilhelmsen" <Mivi_FJERN@FJERN_Hunderupnet.dk> skrev i en meddelelse news:mn.acdc7d5c4055c8c1.11891@FJERNHunderupnet.dk...
>> Hej
>>
>> Jeg er ved at prøve at lave en rutine i en tråd.
>> Ret banalt set, skal der ske det, at når tråden aktiveres, skal et vindue komme op med en progress bar, som stille og roligt bevæger sig ud til enden, for så at starte forfra.
>> Dette lige indtil jeg terminerer tråden.
>
> <klip en masse>
>
> Hvorfor bruger du en tråd til at kalde ShowModal, hvorfor ikke bare kalde Show fra din hovedform og glemme alt om en tråd.
> Men ellers kan du ikke afslutte din tråd med Terminate fordi du ikke checker i Execute om tråden skal afslutte, en tråds Execute metode skal ligne nogen i denne stil:
>
> procedure TMyThread.Execute; // Main execution for thread
> begin
> while not terminated do
> begin
> //noget kode, evt. en sleep
> end;
> end;
>
> /HK


Jeg ved, jeg bare kan vise den i min main form.
Det er ikke mit problem.
Mit problem er vel 2 ting.

Jeg har ikke den store viden om tråde endnu, og jeg kunne godt tænke mig, at lave en tråd, som kunne vise et nyt vindue.
Hvad det vindue så indeholder, ved jeg ikke endnu.
Men jeg vil muligvis lave en slags "venteform" for mine andre programmer, så når de nu "står stille" og laver en eller anden funktion, som tager lang tid, så vil dette vindue
fremkomme, hvor jeg løbende kan skrive noget information.
Nogle af mine programmer er lavet omkring en database, hvor der er temmelig mange data i.
Nogle gange laver brugeren en eller anden form for select, som måske tager 4 - 5 minutter om at returnere.
I den periode virker programmet "dødt".
Derfor vil det være dejligt, hvis jeg kunne lave en form, som fortæller brugeren et eller andet og evt. med en progressbar, som stile og roligt bevæger sig.

Så målet for mig er at lære mere om tråde, og som 1. skridt på vejen at kunne lave ovenstående eksempel.

Michael

--

Best Regards / Venlig hilsen
Michael Vilhelmsen
This is an automatic signature of MesNews.
Site : http://mesnews.no-ip.com



Hans (22-12-2005)
Kommentar
Fra : Hans


Dato : 22-12-05 15:37

"Michael Vilhelmsen"
<Michael.Vilhelmsen.PLEASEREMOVE@Microcom.PLEASEREMOVE.Dk> skrev i en
meddelelse news:mn.b2ad7d5cfa0ecfc1.11460@Microcom.PLEASEREMOVE.Dk...
> Hans explained on 22-12-2005 :
>> "Michael Vilhelmsen" <Mivi_FJERN@FJERN_Hunderupnet.dk> skrev i en
>> meddelelse news:mn.acdc7d5c4055c8c1.11891@FJERNHunderupnet.dk...
>>> Hej
>>>
>>> Jeg er ved at prøve at lave en rutine i en tråd.
>>> Ret banalt set, skal der ske det, at når tråden aktiveres, skal et
>>> vindue komme op med en progress bar, som stille og roligt bevæger sig ud
>>> til enden, for så at starte forfra.
>>> Dette lige indtil jeg terminerer tråden.
>>
>> <klip en masse>
>>
>> Hvorfor bruger du en tråd til at kalde ShowModal, hvorfor ikke bare kalde
>> Show fra din hovedform og glemme alt om en tråd.
>> Men ellers kan du ikke afslutte din tråd med Terminate fordi du ikke
>> checker i Execute om tråden skal afslutte, en tråds Execute metode skal
>> ligne nogen i denne stil:
>>
>> procedure TMyThread.Execute; // Main execution for thread
>> begin
>> while not terminated do
>> begin
>> //noget kode, evt. en sleep
>> end;
>> end;
>>
>> /HK
>
>
> Jeg ved, jeg bare kan vise den i min main form.
> Det er ikke mit problem.
> Mit problem er vel 2 ting.
>
> Jeg har ikke den store viden om tråde endnu, og jeg kunne godt tænke mig,
> at lave en tråd, som kunne vise et nyt vindue.
> Hvad det vindue så indeholder, ved jeg ikke endnu.
> Men jeg vil muligvis lave en slags "venteform" for mine andre programmer,
> så når de nu "står stille" og laver en eller anden funktion, som tager
> lang tid, så vil dette vindue
> fremkomme, hvor jeg løbende kan skrive noget information.
> Nogle af mine programmer er lavet omkring en database, hvor der er
> temmelig mange data i.
> Nogle gange laver brugeren en eller anden form for select, som måske tager
> 4 - 5 minutter om at returnere.
> I den periode virker programmet "dødt".
> Derfor vil det være dejligt, hvis jeg kunne lave en form, som fortæller
> brugeren et eller andet og evt. med en progressbar, som stile og roligt
> bevæger sig.
>
> Så målet for mig er at lære mere om tråde, og som 1. skridt på vejen at
> kunne lave ovenstående eksempel.

Dit program vil stadig være død hvis du gør det på den måde, koden til at
opdatere informationer skal puttes ind i tråden for at det skal virke. Hvis
jeg var dig ville jeg vende det om om putte select koden ind i en tråd
således at hoved programmet ikke dør.

/HK



Michael Vilhelmsen (23-12-2005)
Kommentar
Fra : Michael Vilhelmsen


Dato : 23-12-05 09:45

>
> Dit program vil stadig være død hvis du gør det på den måde, koden til at opdatere informationer skal puttes ind i tråden for at det skal virke. Hvis jeg var dig ville jeg vende det om om putte
> select koden ind i en tråd således at hoved programmet ikke dør.

Og det har jeg gjort.
Virker perfekt.

Takker for hjælpen.

Michael
>
> /HK


--

Best Regards / Venlig hilsen
Michael Vilhelmsen
==========
Best Regards / Venlig hilsen

Michael Vilhelmsen



Michael Vilhelmsen (23-12-2005)
Kommentar
Fra : Michael Vilhelmsen


Dato : 23-12-05 11:35

Hej

Nu har jeg fået lavet en lille tråd (se længere nede), som kan eksekvere en query.
Den virker perfekt, når SQL'en ikke udløser en fejl.

Når min SQL udløser en fejl, hvordan "genfanger" jeg så en exception, så mit program kan fortsætte som jeg forventer ?



I programmet har jeg f.eks. kode som

try
mtExec := TQExec.CreateIt(llQuery);
mtExec.Resume;
repeat
Application.ProcessMessages;
until (ExecDone IN [1,2]);
except
//Her vil jeg gerne ind med præcis den exception som blev udløst i tråden...
end;



Nogen der ved noget om det, eller kan henvise mig til et sted hvor jeg (måske) kan lære det ...

Michael




MIN TRÅD:
unit ExecQuery;

interface

uses
Classes, comctrls, IBQuery;

type
TQExec = class(TThread)
private
mq : TIBQuery;
Answer : integer;
protected
procedure GiveAnswer;
procedure Execute; override;
published
constructor CreateIt (lq : TIBQuery);
destructor Destroy; override;
end;

implementation

uses
windows, UMain;


procedure TQExec.GiveAnswer;
begin
frmMain.ExecDone := Answer;
end;


constructor TQExec.CreateIt;
begin
inherited Create(true);
FreeOnTerminate := TRUE; //Afslutter tråden og rydder op efter udførelse
mq := lq; //Sætter query
Suspended := TRUE; //Starter op ikke aktiv
end;

destructor TQExec.Destroy;
begin
inherited destroy;
end;

procedure TQExec.Execute; // Main execution for thread
begin
Answer := 0;
Synchronize(GiveAnswer);
try
mq.ExecSQL;
Answer := 1;
Synchronize(GiveAnswer);
except
Answer := 2;
Synchronize(GiveAnswer);
end;
end;


end.






--

Best Regards / Venlig hilsen
Michael Vilhelmsen
==========
Best Regards / Venlig hilsen

Michael Vilhelmsen



Mogens Hansen (22-12-2005)
Kommentar
Fra : Mogens Hansen


Dato : 22-12-05 21:57


"Michael Vilhelmsen"
<Michael.Vilhelmsen.PLEASEREMOVE@Microcom.PLEASEREMOVE.Dk> wrote in message
news:mn.b2ad7d5cfa0ecfc1.11460@Microcom.PLEASEREMOVE.Dk...

[8<8<8<]
> Jeg har ikke den store viden om tråde endnu, og jeg kunne godt tænke mig,
> at lave en tråd, som kunne vise et nyt vindue.

Så lad være med at bruge flere tråde - det bliver nemt kompliceret.
Alternativt lær grundigt om tråde, uafhængigt af Delphi og VCL. Kig derefter
på VCL klasserne TThread, TEvent, TCriticalSection etc.

Venlig hilsen

Mogens Hansen



Mogens Hansen (22-12-2005)
Kommentar
Fra : Mogens Hansen


Dato : 22-12-05 21:57


"Michael Vilhelmsen" <Mivi_FJERN@FJERN_Hunderupnet.dk> wrote in message
news:mn.acdc7d5c4055c8c1.11891@FJERNHunderupnet.dk...

[8<8<8<]
> procedure TMyThread.Execute; // Main execution for thread
> begin
> frmVent2.ShowModal;
> end;

Det må man ikke.
Vinduer i MS Windows har hvad man kalder "thread affinity", hvilket reelt
har den konsekvens at hele brugerfladen skal køres fra een tråd.
Hvis man har brug for flere tråde, skal man synkronisere det med
hovedtråden. I VCL gør man det forholdsvis simpelt metoden
TThread.Synchronize


[8<8<8<]
> Jeg har prøvet at ændre frmvent2.showmodal til frmvent2.show, men så
> terminere tråden med det samme med en fejl.

Jeps.

>
> Jeg kan ikke rigtig finde ud af, hvor jeg gør det forkert henne.

Du gør det forkerte at du prøver at lave en flertrådet GUI - det bør man
ikke, og ikke har nogen synkronisering mellem de 2 tråde.

>
> Hvis nogen skulle lige inde med et lille eksempel på en program, som kan
> vise en form via en tråd, og afslutte den igen, vil jeg da gerne se
> det....
> Gerne på mail..

Det er der forhåbentligt ikke nogen der har - for det er ikke sådan man gør.

Jeg har ikke lige Delphi installeret på denne computer - så derfor viser jeg
hvordan du gør i Borland C++Builder, som er det samme som Delphi blot med
C++ som programmeringssprog i stedet for Pascal (Delphi Language). Der er
stort set kun simple syntaktiske forskelle mellem dette C++Builder eksempel
og det tilsvarende Delphi program.

Hovedformen har en "Start" og "Stop" knap - kun een af dem er enabled af
gangen.
I mit eksempel har den anden form også en TProgressBar, men den opdateres
ikke af en timer, men i scope af hovedtråden bestemt af og synkroniseret med
baggrundstråden.


//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <SyncObjs.hpp> // Delphi: uses SyncObjs
#include "Unit1.h"
#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

class TMyThread : public TThread
{
public:
TMyThread();
__fastcall ~TMyThread();

protected:
virtual void __fastcall Execute();

private:
void __fastcall ShowForm2();
void __fastcall HideForm2();
void __fastcall TimerTick();
bool Continue();

private:
TCriticalSection* mutex; // Mutual exclusion
bool cont;
};

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner),
MyThread(0)
{
StopButton->Enabled = false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose)
{
delete MyThread;
MyThread = 0;
CanClose = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::StartButtonClick(TObject *Sender)
{
MyThread = new TMyThread;
StartButton->Enabled = false;
StopButton ->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::StopButtonClick(TObject *Sender)
{
delete MyThread;
MyThread = 0;
StartButton->Enabled = true;
StopButton ->Enabled = false;
}
//---------------------------------------------------------------------------
TMyThread::TMyThread() :
TThread(true),
mutex(new TCriticalSection),
cont(true)
{
Resume();
}
//---------------------------------------------------------------------------
__fastcall TMyThread:TMyThread()
{
mutex->Enter();
cont = false;
mutex->Leave();
WaitFor();
delete mutex;
}
//---------------------------------------------------------------------------
void __fastcall TMyThread::Execute()
{
Form2->ProgressBar1->Position = 0;
Synchronize(ShowForm2);
while(Continue()) {
Sleep(1000);
Synchronize(TimerTick);
}
Synchronize(HideForm2);
}
//---------------------------------------------------------------------------
bool TMyThread::Continue()
{
mutex->Enter();
// Enter critical section and make a non-share copy of the value
bool result = cont;
mutex->Leave();
return result;
}
//---------------------------------------------------------------------------
void __fastcall TMyThread::ShowForm2()
{
// This function is called from the main-thread
Form2->Show();
}
//---------------------------------------------------------------------------
void __fastcall TMyThread::HideForm2()
{
// This function is called from the main-thread
Form2->Hide();
}
//---------------------------------------------------------------------------
void __fastcall TMyThread::TimerTick()
{
// This function is called from the main-thread
Form2->ProgressBar1->Position = (Form2->ProgressBar1->Position + 1) %
Form2->ProgressBar1->Max;
}


Venlig hilsen

Mogens Hansen



Søg
Reklame
Statistik
Spørgsmål : 177435
Tips : 31962
Nyheder : 719565
Indlæg : 6408016
Brugere : 218879

Månedens bedste
Årets bedste
Sidste års bedste