[BCB2007] Wątek - kończenie: Terminated nie działa?

0

Witam,

coś mnie trafi zaraz...
Mam wątek:

class K_PLAYER : public TThread{

	bool bPlaying;				// czy dziala
	int changesize, kierunek;      // testowe

//----------------------------------------------
 protected:
	void __fastcall Execute();

 //----------------------------------------------
 public:
	//----------------------------------------------
	__fastcall K_PLAYER(bool CreateSuspended);
	//----------------------------------------------
	bool Display_Create(void); // tworzy forme
	void Display_Delete(void); // niszczy forme

	//----------------------------------------------
	bool Stop(K_KONFIG * xkConfig);

};
//---------------------------------------------------------------------------

// konstruktor
__fastcall K_PLAYER::K_PLAYER(bool CreateSuspended):TThread(CreateSuspended){

	FreeOnTerminate = false;
	bPlaying = false;
	changesize = 100;
	kierunek = 10;
}

// EXECUTE
void __fastcall K_PLAYER::Execute(){

	bPlaying = true;

	while(!Terminated){
		Beep(changesize, 1);
		Synchronize(Application->ProcessMessages);
		changesize += kierunek;
		if(changesize > 1000) kierunek = -30;
		else if(changesize <= 37) kierunek = 50;
		//frmEkran->Canvas->Lock();
		//frmEkran->Canvas->Ellipse(0 + changesize, 0 + changesize, frmEkran->ClientWidth - changesize, frmEkran->ClientHeight - changesize);
		//frmEkran->Canvas->Unlock();
//		changesize %= 50;
	}
	Beep(500, 100);
	bPlaying = false;
	
	return;
}
//---------------------------------------------------------------------------

// czy watek sie zakonczyl
bool K_PLAYER::Stop(K_KONFIG * xkConfig){

	if(bPlaying){
		return false;
	}

	xkConfig->iXDisp = frmEkran->Left;
	xkConfig->iYDisp = frmEkran->Top;

	return true;
}
//---------------------------------------------------------------------------

Odpalam i zatrzymuję go z zewnątrz:

K_PLAYER * kpPlayer;
void __fastcall TFRoot::BPlayClick(TObject *)
{

	kpPlayer = new (nothrow) K_PLAYER(true);
	if(!kpPlayer){
		return;
	}

	if(!kpPlayer->Display_Create()){
		delete kpPlayer;
		kpPlayer = 0;
		return;
	}

	kpPlayer->Priority = tpNormal;
	kpPlayer->Resume();
}
//---------------------------------------------------------------------------

void __fastcall TFRoot::BStopClick(TObject *)
{
	if(kpPlayer){

		kpPlayer->Terminate();
		Sleep(250);
		for(int i = 0; i < 10; i++){
			if(kpPlayer->Stop(&kConfig)) break;
			kpPlayer->Terminate();
			Application->ProcessMessages();
			Sleep(300);
			Beep(3000, 25);
		}
//		while(kpPlayer->Suspended){
//			kpPlayer->Resume();
//		}
		//Beep(1500, 30);
		//kpPlayer->WaitFor();
		//Beep(1700, 30);

		//kpPlayer->Stop(&kConfig);
		kpPlayer->Display_Delete();

		delete kpPlayer;
		kpPlayer = 0;
	}
}
//---------------------------------------------------------------------------

Kombinowałem różnie różniaście. Teraz jest tak, że jak chcę kończyć wątek to raz na jakiś czas zdarza się że wywoływany w pętli for - kpPlayer->Stop zawsze zwraca false. Używanie WaitFor też nie działa. Zdarza się, że program po prostu wisi i nieskończenie czeka.

Czy sposób obchodzenia się z wątkiem jest poprawny? Bo już sam nie wiem. Najbardziej nie podoba mi się sprawdzanie bPlaying w K_PLAYER::Stop.

0

wykasuj to: Synchronize(Application->ProcessMessages);
W połączeniu z WaitFor to tworzy zakleszczenie i program wisi. Zresztą co to twoim zdaniem ma robić. Synchronize działa zupełnie inaczej i aż dziw bierze, że ci się to po prostu nie kraszuje.
Nie będę ukrywał, że nie wszystko rozumiem z twojego kodu.

A i jeszcze to Beep(500, 100); mnie niepokoi! Co i w jakich jednostkach przyjmuje to Beep (domyślam się, że częstotliwość i czas)?
Po co bawisz się wielowątkowością, to spokojnie można zrobić TTimer'em.

0

Kod jest po prostu przykładowy. Beep'y są tylko po to, żebym słyszał jak sobie wątek chodzi i kiedy się kończy.
Faktycznie usunięcie Synchronize(Application->ProcessMessages); pomogło. Nie udało mi się na razie uzyskać błędu.

Pytanie jeszcze tylko, czy takie sprawdzanie zmiennej K_PLAYER::bPlaying jak jest teraz jest OK? Nie ma czasem możliwości, że gdy ja sprawdzam jej stan w K_PLAYER::Stop() to w K_PLAYER::Execute() akurat jest ona ustawiana?

0

Poczytaj o sekcjach krytycznych. Jeśli się nie mylę jest taka klasa w BCB TCriticalSection.

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