Toon posts:

[C>Win32>Threads] Hoe data best 'statisch' houden?

Pagina: 1
Acties:

Verwijderd

Topicstarter
Het zit dus zo :

Ik heb een thread die om de 5 minuten aangeroepen wordt in het hoofdprogramma. Deze thread checkt een POP3 account. De laatste return string van de pop3 server die bevat hoeveel mails er zijn (+OK 2 820) moet worden opgeslagen op zo'n manier dat de volgende keer als de thread word aangeroepen deze data nog steeds beschikbaar is. Voorlopig gebruik ik dus een string die static is (static char szLastReturned[512]), maar dit schijnt niet steeds 100% te werken. Dus vroeg ik me af of er geen andere (betere) manier was om data 'vast' te houden tussen threads. Wegschrijven naar het register of een file is echt wel de laatste optie die ik wil overwegen.

  • Primal
  • Registratie: Augustus 2001
  • Laatst online: 11-09 14:32
Volgens mij is het probleem dat jij hebt de synchronisatie van data die gebruikt wordt door meerdere threads?! Am I correct? Met andere woorden: die string wordt door meerdere threads gebruikt?

Is dat het geval dan heb je meteen het al-oude probleem van meerdere threads te pakken. :)
Waar je in ieder geval voor moet zorgen is dat wanneer thread 1 uit de string gaat zitten lezen, thread 2 die string ondertussen niet gaat zitten wijzigen. Dit kun je oplossen door mutexen/events/critical sections rondom je code te plaatsen waarin de variabele wordt geraadpleegd of gewijzigd. Naar file of registry wegschrijven is niet echt een optie omdat hetzelfde probleem blijft bestaan.

Maar wat is nou de beste oplossing? Tja, dat is met dit soort gevallen altijd moeilijk. Je zou een stukje 'shared' memory kunnen aanmaken waaruit de threads kunnen lezen en/of schrijven maar het probleem blijft altijd.

Kun je misschien iets specifieker beschrijven wat je programma doet (inclusief threads)? Mag ook met (pseudo) C-code erbij.

"The fastest code, is the code that is never called."


  • igmar
  • Registratie: April 2000
  • Laatst online: 09-09 19:53

igmar

ISO20022

Ik heb een thread die om de 5 minuten aangeroepen wordt in het hoofdprogramma. Deze thread checkt een POP3 account. De laatste return string van de pop3 server die bevat hoeveel mails er zijn (+OK 2 820) moet worden opgeslagen op zo'n manier dat de volgende keer als de thread word aangeroepen deze data nog steeds beschikbaar is. Voorlopig gebruik ik dus een string die static is (static char szLastReturned[512]), maar dit schijnt niet steeds 100% te werken. Dus vroeg ik me af of er geen andere (betere) manier was om data 'vast' te houden tussen threads. Wegschrijven naar het register of een file is echt wel de laatste optie die ik wil overwegen.
Gebruik je een mutex ? Dat zou moeten werken in combinatie met een global variabele.

Verwijderd

Topicstarter
Op maandag 04 maart 2002 20:07 schreef Primal het volgende:
Volgens mij is het probleem dat jij hebt de synchronisatie van data die gebruikt wordt door meerdere threads?! Am I correct? Met andere woorden: die string wordt door meerdere threads gebruikt?

Kun je misschien iets specifieker beschrijven wat je programma doet (inclusief threads)? Mag ook met (pseudo) C-code erbij.
Neen, niet echt... Hoewel... :o Het is beetje moeilijk uit te leggen... Misschien dat de code helpt

Ik heb nu dus deze code (even verkort)
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
DWORD WINAPI CheckMail( LPVOID lpParam )
{
  static char szReturnedString[512]
  // pop 3 code, server response lezen
  if( !strcmp(szServerResponse, szReturnedString) )
  { 
    // er is nieuwe mail, messagebox en zooi
    strcpy( szReturnedString, szServerResponse );
  }
}

// in de mailwindow
MessageProc( ... )
{
 // messageswitch statement ....
 case WM_CREATE:
    SetTimer( .... );
  break;
 case WM_TIMER:
     CreateThread( ..., CheckMail, .... );
 break;
}

(de pop3 code zit in een thread zodat het programma niet volledig 'lockt' als ie de mail checkt.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 13-09 15:13
In dit geval zou het gebruik van een mutex (locken voordat je 'm gebruikt en releasen als je er mee klaar bent) uitkomst bieden.

Als je kan garanderen dat de thread altijd in z'n eentje draait, heb je die niet nodig. Ik kan me namelijk voorstellen dat je in dit specifieke geval geen nieuwe thread wilt starten als de oude nog niet afgesloten is. Als de server dusdanig traag is of de hoeveelheid mail dusdanig groot dat 'ie niet in 5 minuten klaar is, wil je neem ik aan eerst de laatste sessie afronden voordat je een nieuwe begint (waarbij je kunt overwegen dit helemaal achterwege te laten).

edit:
In dit geval heb je natuurlijk ook een mutex nodig, maar dan om te kunnen vaststellen of de thread nog draait of niet.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Daar je niet buiten het proces gaat kun je hier ook gewoon een critical section gebruiken ipv een mutex, wat een stuk sneller is.

Schoonheidsprijzen kun je hier overigens verdienen met een named file mapping, zoek eens in MSDN naar CreateFileMapping, maar echt nodig is het niet: gewoon global memory met een critical section ben je klaar.

Wellicht nog schoner is om naar Soultaker te luisteren en ervoor te zorgen dat je nooit 2 polls tegelijk kunt doen. Daar pak je echter geen mutex voor (foei! ;) ) maar dan maak je met CreateWaitableTimer een timed event object aan, en dan kun je met WaitForMultipleObjects op deze timer EN op de thread wachten totdat allebei de voorwaarden voldaan zijn, oftewel de 5 minuten zijn verstreken EN de thread is klaar.

* curry684 voelt dat er een vraag om meer uitleg gaat komen :Y)

Professionele website nodig?


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op maandag 04 maart 2002 20:58 schreef Soultaker het volgende:
edit:
In dit geval heb je natuurlijk ook een mutex nodig, maar dan om te kunnen vaststellen of de thread nog draait of niet.
Uhhhh....
code:
1
2
3
4
5
6
7
8
if(WaitForSingleObject(ThreadHandle, 0) == WAIT_OBJECT_0)
  {
  // Thread is klaar
  }
else
  {
  // Thread is niet klaar
  }

Professionele website nodig?


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 13-09 15:13
Ah ja, dat kan natuurlijk ook =) Weer wat geleerd.

Het voordeel van een mutex gebruiken is dat het ook in een multithreaded omgeving werkt, hoewel dat in het geval van een event handler (dit geval dus) waarschijnlijk niet nodig is.

  • Primal
  • Registratie: Augustus 2001
  • Laatst online: 11-09 14:32
Juist ja. Zoals ik al in mijn eerdere post (net als curry684
en Soultaker) zei kun je dit probleem verhelpen door het gebruik van mutexen/events/critical sections. Indien je een mutex of critical section gebruikt moet je die dus overal om je code zetten waarin je de variabele raadpleegt/wijzigt. Op deze manier kan het dus nooit voorkomen dat de ene thread bezig is met de variabele te lezen (of een stringcompare te doen als in jouw code) en de andere is hem aan het updaten.

En inderdaad wachten op een thread kan ook met WaitForSingle object, wat ik <promotie-mode on> zelf verreweg de mooiste oplossing vind. <promotie-mode off> :)

"The fastest code, is the code that is never called."


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op maandag 04 maart 2002 21:56 schreef Primal het volgende:
En inderdaad wachten op een thread kan ook met WaitForSingle object, wat ik <promotie-mode on> zelf verreweg de mooiste oplossing vind. <promotie-mode off> :)
Maar als je een waitable timer op 5 minuten zet zoals ik suggereerde is het <promotiemode on> helemaal geilig mooi als je dan met WaitForMultipleObjects met WaitAll op TRUE kunt wachten tot zowel de 5 minuten voorbij zijn als de thread klaar is!!! <promotiemode off> :Y)

edit:

Oeps was even de smiley vergeten maar Primal snapte 'm al :P

Professionele website nodig?


Verwijderd

Topicstarter
woei bedankt iedereen, ga het dan even proberen met een globale var.
En inderdaad wachten op een thread kan ook met WaitForSingle object, wat ik <promotie-mode on> zelf verreweg de mooiste oplossing vind. <promotie-mode off>
Jah, maar ik hoef niet te wachten op de thread. De thread werd juist aangemaakt omdat het hoofdprogramma moet verder werken terwijl de mail word gecheckt. Het enige wat ik moet voorkomen is dat de thread dubbel word opgestart.
:)

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Okee de volgende hobbycode compileert, ik heb 'm niet gebruikt maar ik verwacht dat ie het wel doet.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// --------------------------------------------------------------------------

// Define sufficient windows version (NT4 or 98+)
#ifndef _WIN32_WINDOWS
  #define _WIN32_WINDOWS 0x0410
#endif

#include <windows.h>
#include <stdio.h>
#include <conio.h>

// --------------------------------------------------------------------------
// Type definitions
// --------------------------------------------------------------------------

typedef enum
  {
  e_HiTimer    = 0,
  e_HiThread   = 1,
  } t_HandleIndex;

// --------------------------------------------------------------------------
// Constants
// --------------------------------------------------------------------------

// Standard repeat timeout is 5 minutes
const LARGE_INTEGER     c_Timeout     = { 3000000000 };

// --------------------------------------------------------------------------
// ExecuteServerThread
// --------------------------------------------------------------------------

DWORD WINAPI ExecuteServerThread(LPVOID p_ShutdownEvent)
{
HANDLE        l_Handles[2];

// Initialize the waitable timer for this server thread
l_Handles[e_HiTimer]    = CreateWaitableTimer(NULL, FALSE, NULL);

// Run eternally until shutdown requested
while(WaitForSingleObject((HANDLE)p_ShutdownEvent, 0) == WAIT_TIMEOUT)
  {
  // Set the timer to 5 minutes
  if(!SetWaitableTimer(l_Handles[e_HiTimer], &c_Timeout, NULL, NULL, NULL, FALSE))
    return GetLastError();
  
  // Create the thread
  l_Handles[e_HiThread] = CreateThread(......);     // START RETRIEVAL THREAD HERE
  
  // Now wait for both the 5 minutes to expire and the thread to finish
  if(WaitForMultipleObjects(2, l_Handles, TRUE, INFINITE) == WAIT_FAILED)
    return GetLastError();
  }

// Return without error
return 0;
}

// --------------------------------------------------------------------------
// Main function
// --------------------------------------------------------------------------

int main()
{
HANDLE    l_ShutdownEvent;
HANDLE    l_ServerThread;
DWORD      l_ThreadId;

// Initialize the shutdown event and the server thread
l_ShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
l_ServerThread  = CreateThread(NULL, NULL, ExecuteServerThread, 
                     l_ShutdownEvent, 0, &l_ThreadId);

// Wait for keypress
printf("Press enter to shut down server...");
while(!getchar());

// Set the event for thread shutdown then wait until it is dead
SetEvent(l_ShutdownEvent);
WaitForSingleObject(l_ServerThread, INFINITE);

// TODO: Check for error conditions here

// Close the handles
CloseHandle(l_ServerThread);
CloseHandle(l_ShutdownEvent);

// Return without error
return 0;
}

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

Professionele website nodig?


Verwijderd

Op maandag 04 maart 2002 23:04 schreef SpHeaRe het volgende:
woei bedankt iedereen, ga het dan even proberen met een globale var.
Gooi die dan ff in een speciaal namespace'je, das wel zo netjes :).

Verwijderd

Topicstarter
Op maandag 04 maart 2002 23:42 schreef Sneechy het volgende:

[..]

Gooi die dan ff in een speciaal namespace'je, das wel zo netjes :).
bwah voor die ene globale var lijkt me het niet echt nodig :)

btw Curry: tnx voor het voorbeeld. Ik zal het eens grondig bestuderen ;)

maar nu gaat /me slapen... blergh morgen school

Verwijderd

Op dinsdag 05 maart 2002 00:14 schreef SpHeaRe het volgende:
voor die ene globale var lijkt me het niet echt nodig
Oei oei oei, dit soort EVIL uitspraken zijn vaak het begin van het einde :Y).

  • Primal
  • Registratie: Augustus 2001
  • Laatst online: 11-09 14:32
Op maandag 04 maart 2002 22:09 schreef curry684 het volgende:

[..]

Maar als je een waitable timer op 5 minuten zet zoals ik suggereerde is het <promotiemode on> helemaal geilig mooi als je dan met WaitForMultipleObjects met WaitAll op TRUE kunt wachten tot zowel de 5 minuten voorbij zijn als de thread klaar is!!! <promotiemode off>
Hehe :)

"The fastest code, is the code that is never called."

Pagina: 1