jeszcze raz watki

0

witam serdecznie.
nie moge sobie poradzic z jedna rzecza.
moj program posiada jeden rownolegly watek. program jak i dodatkowy watek zadaje pytania serwerowi SQL. kiedy program chce zadac pytanie ustawia flage informujaca watek, zeby on nie robil tego samego. tymczasem w watku przed zadaniem pytania wchodze w sekcje krytyczna, co powinno zapobiec przerwaniu watku i przekazaniu sterowania do programu. kiedy watek lub program zadaje pytanie nie moze sie zdazyc, ze przed otrzymaniem odpowiedzi windows przelaczy sie z watku do programu lub odwrotnie i pozwoli na zadanie kolejnego pytania, zanim jeszcze dostanie odpowiedz z serwera. efekt bedzie taki, ze serwer SQL otrzyma dwa pytania po kolei bez mozliwosci odpowiedzenia na pierwsze z nich. wydawaloby sie, ze flaga informujaca watek, zeby nie wykonywal polecen, ktore zawiera w ciele jego funkcji, gdy program wysyla zapytanie i oczekuje na odpowiedz i sekcja krytyczna w samym watku powinny wystarczyc ale wyglada na to ze pomimo sekcji krytycznej windows przelacza sterownie, poniewaz otrzymuje bledy z serwera SQL, dotyczace wysylania dwoch zapytania bez proby odczytania odpowiedzi na pierwsze z nich. dodatkowo w samym programie sprawdzam ustawienie flagi sql.temp, ktora ustawia sam watek na TRUE po wejsciu juz w sekcje krytyczna i ustawia ponownie na FALSE przed wyjsciem z tej samej sekcji. wydaje mi sie, ze program nigdy nie powinien byc w sytuacji, ze odczytuje flage ustawiona przez watek i zastaje w niej wartosc TRUE, poniewaz flaga ta jest ustawioana na TRUE i chwile potem na FALSE wewnatrz sekcji krytycznej.
oto kod watku:

DWORD WINAPI threadProc_KeepConectionAlive(int pParam)							//podtrzymywanie polaczenia
{
	CRITICAL_SECTION cs1 ;
	InitializeCriticalSection ( &cs1 ) ;

	char txt[200];
	int start,end;
	static int count;
	int temp;


	while (TRUE)
	{

		//czy program nie wysyla zapytania
		while( sql.SQL_QUERY_STATUS == TRUE )
		{
			Sleep( sql.SQL_QUERY_STATUS_WAIT );
		}
		EnterCriticalSection ( &cs1 ) ;											//wejscie do sekcji krytycznej.
//-----------------------------------------
sql.temp = TRUE;
	
		//Beep(100,100);

		start = GetTickCount();
		
		otl_stream i(1,"select ID from LOG_ERROR where ID = 1",db);
		i>> temp;
		//sql.serverLogOff();
		//sql.logon();

		end = GetTickCount();

		wsprintf(txt,"thread time: %d",end-start);
		SetWindowText(hwndMessage[1],txt);
		
		wsprintf(txt,"thread count: %d",count++);
		SetWindowText(hwndMessage[2],txt);


//-----------------------------------------
sql.temp = FALSE;

		LeaveCriticalSection ( &cs1 ) ;	
	//wyjscie z sekcji krytycznej.
		Sleep( sql.THREAD_DURATION_CONNECTION );
	}

		
	DeleteCriticalSection ( &cs1 ) ;												//skasowanie sekcji kiedy nie jest juz potrzebna.

return FALSE;
}

nie wiem, czy moze cos zle robie jesli chodzi o sekcje krytyczna, ze nie spelnia swojego zadania czy problem jest gdzie indziej. mecze sie juz nad tym drugi dzien i nie moge dojsc do zrodla problemu. chetnie odpowiem na dodatkowe pytania, jesli to co napisalem nie jest wystarczajace.

pozdrawiam
Mariusz

0

Żadna flaga Ci nie potrzebna. Sekcją krytyczną możesz rozwiązać cały problem - i program, i wątek mają rywalizować o wejście do tej sekcji. W sekcji ma odbywać się pojedyncze zapytanie, pobranie wyniku i jej opuszczenie, by konkurent mógł z niej skorzystać.

Sekcja krytyczna nie gwarantuje ciągłości i braku przerwania wątków. Gwarantuje, że tylko jeden wątek będzie w danej chwili w takiej sekcji. Inne muszą poczekać. Dopiero, jak on wyjdzie z sekcji, inne mogą o nią rywalizować.

0

No chwila, ale ale synchronizacja sekcjami krytycznymi polega na tym, że dwa lub więcej wątków korzysta z tej samej sekcji, a u ciebie tego nie ma.

CRITICAL_SECTION cs1; //<--- to musi być dostępne dla obu wątków
0

Dobrze, rozumiem teraz.
Po pierwsze musze zdefiniowac obiekt sekcji krytycznej gdzies na zewnatrz najlepiej, zeby wszystki watki korzystaly z jednej i o nia rywalizowaly, bo z tego co napisales, dotyczy ona tylko watkow.
Po drugie, skoro program moze jednak przerywac watek, nawet jesli jest w sekcji krytycznej, powinienem przed wykonaniem jakiegokolwiek zapytania w programie czy watku ustawic flage, a przed jej ustawieniem sprawdzic, czy juz nie zostala ustawiona przez inny fragment programu, co, jesli nastapilo poczekac, az zostanie wylaczona (moze bardziej pasuje opuszczona) i dopiero ja ustawic i wykonywac zapytanie. Ewentualnie, jesli dobrze rozumiem, korzystac z sekcji krytycznej rowniez w glownym watku programu (z tego co piszesz, wyglada, ze mozna to rowniez robic).
To chyba powinno rozwiazac sprawe. Sprawdze dzis wieczorem i napisze co sie dzieje.

W kazdym razie bardzo dziekuje za uwagi. Zawsze mozna na Was liczyc :-)

Mariusz

0

[...] bo z tego co napisales, dotyczy ona tylko watkow.

Wątków i procesu głównego aplikacji - do synchronizacji miedzy procesami służa semafory, mutexy etc.

Po drugie, skoro program moze jednak przerywac watek, nawet jesli jest w sekcji krytycznej, powinienem przed wykonaniem jakiegokolwiek zapytania w programie czy watku ustawic flage, a przed jej ustawieniem sprawdzic, czy juz nie zostala ustawiona przez inny fragment programu, co, jesli nastapilo poczekac, az zostanie wylaczona (moze bardziej pasuje opuszczona) i dopiero ja ustawic i wykonywac zapytanie

Nie wiem czy dobrze zrozumiałem, ale możesz poeksperymentować pętlą komunikatów - coś na wzór głównej pętli programu. Zabawy z flagami przy więcej niż dwóch wątkach mogą być kłopotliwe.

0

problem rozwiazałem.
wystarczyło użyć sekcji krytycznych również w głównym wątku programu.
Nie pisałbym o tym pewnie, ale zauważyłem przy okazji, że Windows dziwnie zachowuje się w sytuacji gdy wątek jest w sekcji krytycznej i wykonuje proste polecenie:

SendMessage ( main.hwnd_status, SB_SETTEXT, 7, (LPARAM) txt ) ;

  • czyli ustawienie tekstu w jednym z pól paska statusu. To dziwne zachowanie objawia się tym, że program nadal działa (sprawdziłem debugerem) ale urywa się kontakt z interfejsem aplikacji. Krótko mówiąc Windows przestaje w ogóle odśwież okna i wszystko wygląda jakby zawisło. Nie da się nawet zminimalizować czy zmaksymalizować aplikacji. Wstawiam zatem tekst do status bara po wyjściu z sekcji krytycznej. Nie rozumiem czemu się tak dzieje.

ps. od kilku dni oglądam sobie kursy c# dostępne na stronie Microsoftu.
Nie byłem nim wcześniej zainteresowany bo wiem, że jeszcze sporo przede mną jeśli chodzi o C++ ale wrażenia mam tak pozytywne, że chyba zostawie C++.
Polecam wszystkim, którzy jeszcze nie mieli okazji przyjżeć się temu językowi.

Pozdrawiam serdecznie i dziękuję jeszcze raz wszystkim za pomoc.
Mariusz

0

Jeśli twój głóny wątek zajmujący się oknami i całą resztą musi długo czekać na sekcje krytyczną, z której właśnie ort! drugi wątek to sie wszystko przywiesza. Użyj MsgWaitForMultipleObjects w głównej pętli programu czekając na message lub sekcje krytyczną. Niech pierwszy wątek po wejściu w sekcje krytyczną zajmie sie rysowaniem. Tak samo drugi wątek, po oddaniu sekcji krytycznej czekając na ponowne do niej wejście niech już komunikuje sie z serwerem i buforuje odpowiedzi.

1 użytkowników online, w tym zalogowanych: 0, gości: 1