/ Forside / Teknologi / Udvikling / C/C++ / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
C/C++
#NavnPoint
BertelBra.. 2425
pmbruun 695
Master_of.. 501
jdjespers.. 500
kyllekylle 500
Bech_bb 500
scootergr.. 300
gibson 300
molokyle 287
10  strarup 270
Windows-programmering: Nedlæggelse af tråd~
Fra : Thomas Arildsen


Dato : 04-12-01 23:03

Hvordan nedlægger man "pænt" en kørende tråd oprettet med CreateThread()
udefra på et vilkårligt tidspunkt? Jeg kan forstå, at TerminateThread() er
en meget uheldig løsning, som da også tilsyneladende giver problemer med en
CRITICAL_SECTION, som ikke frigives ved nedlæggelse af tråden og skal bruges
af andre efterfølgende.
Jeg går ud fra, at det er mest korrekt at få tråden til selv at køre
ExitThread(), men hvordan kan man til et vikårligt tidspunkt signalere den
udefra til at gøre det? Den pågældende tråd "sover" det meste af tiden,
hvorved jeg, som det er nu, kan risikere at skulle vente i temmelig lang tid
på, at den "vågner" og evt. ser på et eksternt sat flag, at den skal
nedlægge sig selv. Ud fra, hvad jeg har læst mig til på MSDN, har jeg fået
den idé, at jeg kan lade tråden sove med SleepEx() og så koble en
APC-funktion, som kører ExitThread(), på den, når den skal nedlægge sig. Den
laver så lidt, mens den ikke sover, at jeg godt kan tåle at vente til den
sover, før ExitThread() køres.
Er det fuldstændig vanvittigt, det jeg har fundet frem til, og vil det
overhovedet fungere? Jeg vil naturligvis helst gøre det på den korrekte
måde, så jeg håber, nogen her kan fortælle mig lidt om det.

Mvh. Thomas Arildsen



 
 
Mogens Hansen (04-12-2001)
Kommentar
Fra : Mogens Hansen


Dato : 04-12-01 23:26


"Thomas Arildsen" <tari00@kom.auc.dk> wrote in message
news:9ujh11$l5n$1@sunsite.dk...
> Hvordan nedlægger man "pænt" en kørende tråd oprettet med CreateThread()
> udefra på et vilkårligt tidspunkt? Jeg kan forstå, at TerminateThread() er
> en meget uheldig løsning, som da også tilsyneladende giver problemer med
en
> CRITICAL_SECTION, som ikke frigives ved nedlæggelse af tråden og skal
bruges
> af andre efterfølgende.

TerminateThread er absolut ikke pænt!

> Jeg går ud fra, at det er mest korrekt at få tråden til selv at køre
> ExitThread(), men hvordan kan man til et vikårligt tidspunkt signalere den
> udefra til at gøre det?

ExitThread bliver ifølge dokumentationen kaldt, når thread-funktionen
returnerer.

Lav en event-semaphor, med CreateEvent, som der signaleres på når tråden
skal stoppe.
Lad tråden vente på den i toppen af en løkke i tråd-funktionen med
WaitForMultipleObjects, hvor den også venter på at få besked om at lave
noget fornuftigt eller at afslutte.

> Den pågældende tråd "sover" det meste af tiden,
> hvorved jeg, som det er nu, kan risikere at skulle vente i temmelig lang
tid
> på, at den "vågner" og evt. ser på et eksternt sat flag, at den skal
> nedlægge sig selv. Ud fra, hvad jeg har læst mig til på MSDN, har jeg fået
> den idé, at jeg kan lade tråden sove med SleepEx() og så koble en

Prøv generelt at undgå at bruge Sleep og SleepEx til at styre hvornår en
tråd skal lave noget.
Det ødelægger enter trådens evne til at svare på hændelser eller programmets
evne til at skalere.
Husk også at programmer ikke generelt bliver hurtigere af at blive
multi-trådet - tværtimod. Men hvis vi snakker asynkrone eksterne hændelser,
multi-processor maskiner eller en GUI's evne til at reagere så er der
naturligvis en pointe.

Generelt vil jeg igen anbefale bogen
Pattern-Oriented Software Architecture: Patterns for Concurrent and
Networked Objects
Douglas C. Schmidt
Michael Stal
Hans Rohnert and
Frank Buschmann
ISBN 0-471-60695-2

hvor der står meget godt om multi-trådet programmering.

Det er i forvejen noget der ligner en størrelsesorden sværere at lave
(stabile) multi-trådet programmer end at lave enkelt trådet programmer.
Hvis det ikke bliver designet ordentligt fra starten bliver det værre.

Venlig hilsen

Mogens Hansen



Thomas Arildsen (05-12-2001)
Kommentar
Fra : Thomas Arildsen


Dato : 05-12-01 09:20

"Mogens Hansen" <mogens_h@dk-online.dk> skrev i en meddelelse
news:9ujie6$cv2$1@news.cybercity.dk...
...Resumé forkortet...
> Det er i forvejen noget der ligner en størrelsesorden sværere at lave
> (stabile) multi-trådet programmer end at lave enkelt trådet programmer.
> Hvis det ikke bliver designet ordentligt fra starten bliver det værre.

Grunden til, at multitrådet programmering blev valgt var, at programmet
simulerer nogle skibe, som sejler. Jeg har så skrevet en skibs-klasse, som
selv kan simulere sin sejlads, og så kan det så overlades til hvert enkelt
skibs-objekt at sørge for simulation.
Meningen med wait funktionen var så, at et skib skulle rykke sin position
f.eks. et sekund ad gangen.
Skal jeg så forstå det sådan, at den gode og gennemtænkte måde at gøre det
på, ville være istedet at implementere denne venten på, at skibet skal
rykkes et stykke næste sekund, som f.eks. en WaitableTimer, som der ventes
ved i toppen af "simulations-løkken". Samme sted kan man så vente på et
Event, som man kan signalere andre steder fra i programmet, når man ønsker,
at skibet skal stoppe med at simulere. Hvordan håndterer man så, at det ikke
er det samme, der skal ske, når det er timeren, der signalerer
WaitForMultipleObjects (tag endnu en tur rundt i løkken), som når det er
afslutnings-Event'et, der signalerer WaitForMultipleObjects (hop ud af
løkken og afslut).
Det er rart at få nogle inputs fra en, der har forstand på tingene.

Mvh. Thomas Arildsen



Mogens Hansen (06-12-2001)
Kommentar
Fra : Mogens Hansen


Dato : 06-12-01 22:18


"Thomas Arildsen" <tari00@kom.auc.dk> wrote in message
> "Mogens Hansen" <mogens_h@dk-online.dk> skrev i en meddelelse

> ...Resumé forkortet...
> > Det er i forvejen noget der ligner en størrelsesorden sværere at lave
> > (stabile) multi-trådet programmer end at lave enkelt trådet programmer.
> > Hvis det ikke bliver designet ordentligt fra starten bliver det værre.
>
> Grunden til, at multitrådet programmering blev valgt var, at programmet
> simulerer nogle skibe, som sejler. Jeg har så skrevet en skibs-klasse, som
> selv kan simulere sin sejlads, og så kan det så overlades til hvert enkelt
> skibs-objekt at sørge for simulation.

Ok
Jeg kan godt se at der er nærliggende at gøre hvert skibs-objekt
selveksekverende - stort set som i den virkelige verden.

> Meningen med wait funktionen var så, at et skib skulle rykke sin position
> f.eks. et sekund ad gangen.

Det er naturligvis altid "farligt" at udtale sig, for det er jo ikke sikkert
at man har forstået alle detaljer, men jeg prøver alligevel.

Umiddelbart ville jeg lave simuleringen således at alle skibs-objekter blev
bedt om at tage et skridt i simuleringen, hvor de så selv afgør i det
skridt, hvordan det vil bevæge sig.
Når alle skibe har taget et skridt kan man set hvordan den samlede situation
er.
Det kan gøres meget simpelt i en enkelt tråd.

Noget i retningen af:

#include <vector>
#include <algorithm>
#include <functional>
#include <string>
#include <iostream>

class ship
{
public:
ship(const char* name, int speed_x, int speed_y);
~ship(void); // make virtual if used as base-class

static void step(void);

private:
void do_step(void); // make pure virtual if used as base-class

std::string name_;
int speed_x_, speed_y_;
int position_x_, position_y_;

static std::vector<ship*> all_ships;

private:
// copy constructor and copy assignment not implemented
ship(const ship&);
ship& operator=(const ship&);
};

std::vector<ship*> ship::all_ships;

ship::ship(const char* name, int speed_x, int speed_y) :
name_(name),
speed_x_(speed_x),
speed_y_(speed_y),
position_x_(0),
position_y_(0)
{
all_ships.push_back(this);
}

ship:ship()
{
all_ships.erase(std::find(all_ships.begin(), all_ships.end(), this));
}

void ship::step(void)
{
std::for_each(all_ships.begin(), all_ships.end(),
std::mem_fun(&ship::do_step));
}

void ship::do_step(void)
{
position_x_ += speed_x_;
position_y_ += speed_y_;
std::cout << name_ << " position:" << position_x_ << ", " << position_y_
<< "\n";
}

int main(void)
{
ship blue_oyster("Blue Oyster", 1, 1);
ship golden_ocean("Golden Ocean", 10, 10);

for(unsigned i = 0; 10 != i; ++i) {
ship::step();
std::cout << std::endl;
// sleep here if needed
}
}

> Hvordan håndterer man så, at det ikke
> er det samme, der skal ske, når det er timeren, der signalerer
> WaitForMultipleObjects (tag endnu en tur rundt i løkken), som når det er
> afslutnings-Event'et, der signalerer WaitForMultipleObjects (hop ud af
> løkken og afslut).

Returnværdien fra WaitForMultipleObjects indikerer hvilket object, der er
blevet signaleret på.
Dette kan så bruges til at afgøre, hvad det er der skal gøres.

Venlig hilsen

Mogens Hansen



Thomas Arildsen (07-12-2001)
Kommentar
Fra : Thomas Arildsen


Dato : 07-12-01 00:07


"Mogens Hansen" <mogens_h@dk-online.dk> wrote in message
news:9uon65$6ha$1@news.cybercity.dk...
> Umiddelbart ville jeg lave simuleringen således at alle skibs-objekter
blev
> bedt om at tage et skridt i simuleringen, hvor de så selv afgør i det
> skridt, hvordan det vil bevæge sig.
> Når alle skibe har taget et skridt kan man set hvordan den samlede
situation
> er.
> Det kan gøres meget simpelt i en enkelt tråd.
....Resumé forkortet...

Jeg tror nu nok, det er bedst at bibeholde "et skib - én tråd"-filosofien;
der skal også ske andre ting med hvert skib, hvor intervallet med hvilket
det sker, er afhængig af det enkelte skibs fart, så de kan ikke umiddelbart
skæres over én kam. Jeg kan imidlertid godt se, hvad du mener, og det ville
være praktisk, hvis de alle skulle gøre det samme på samme tid.

> Returnværdien fra WaitForMultipleObjects indikerer hvilket object, der er
> blevet signaleret på.
> Dette kan så bruges til at afgøre, hvad det er der skal gøres.

Aha, ja så kan jeg godt se, hvordan det burde gøres.
Jeg takker mange gange for de mange værdifulde ideer og forklaringer.

Mvh. Thomas Arildsen



Anders Borum (04-12-2001)
Kommentar
Fra : Anders Borum


Dato : 04-12-01 23:40

"Thomas Arildsen" <tari00@kom.auc.dk> skrev i en meddelelse
news:9ujh11$l5n$1@sunsite.dk...
[klip]
> Er det fuldstændig vanvittigt, det jeg har fundet frem til, og vil det
> overhovedet fungere? Jeg vil naturligvis helst gøre det på den korrekte
> måde, så jeg håber, nogen her kan fortælle mig lidt om det.

Goddag Thomas.

Jeg lod mig på et tidspunkt inspirere af java og muligheden for at få kastet
en InterruptedException i tråden når denne bliver termineret (blødt) udefra.
På gode operativsystemer som nt eller 2k kan det givetvis laves med
funktionerne i <signal.h>, men jeg skulle have det til at fungere under
win95.

Løsningen blev at ændre trådens program-counter direkte vha. kald til
GetThreadContext og SetThreadContext. Så kunne tråden tvinges til selv at
kaste den ønskede undtagelse, som måske -måske ikke blev fanget andetsteds.
Det fungerede ret godt idét destruktorer blev kaldt som forventet.

Det er nu næppe er _den_korrekte_måde_ at gøre det på.

Hilsen Anders





Thomas Arildsen (05-12-2001)
Kommentar
Fra : Thomas Arildsen


Dato : 05-12-01 09:23

"Anders Borum" <aborum@hotmail.com> skrev i en meddelelse
news:nicP7.2731$z4.312565@news000.worldonline.dk...
> Løsningen blev at ændre trådens program-counter direkte vha. kald til
> GetThreadContext og SetThreadContext. Så kunne tråden tvinges til selv at
> kaste den ønskede undtagelse, som måske -måske ikke blev fanget
andetsteds.
> Det fungerede ret godt idét destruktorer blev kaldt som forventet.
>
> Det er nu næppe er _den_korrekte_måde_ at gøre det på.

Der vil jeg nok give dig ret; det er vist en tand for hardcore til, at det
der noget jeg bør kaste mig ud i her.

Mvh. Thomas Arildsen



Søg
Reklame
Statistik
Spørgsmål : 177552
Tips : 31968
Nyheder : 719565
Indlæg : 6408847
Brugere : 218887

Månedens bedste
Årets bedste
Sidste års bedste