[C++ Builder] TImage, wątek, obrazek z internetu

0

trochę się uczę i tak sobie wymysliłem, żeby googlowską mapkę przenieść na TImage

mam klasę która jest odpowiedzialna za rysowanie
w niej mam metodę która w dwóch pętlach po x-ach i po y-kach tworzy url-a

void  mapa::obrazki(int iX,int iY)//pozycja lewy górny róg 
{ 
      /*zmienne - np obliczanie po wielkości TImage ile wejdzie obrazków w pionie i w poziomie */ 
      for(i=iX;i<iXMax;i++) 
      { 
             for(j=iY;j<iYMax;j++) 
             { 
                   strULR = /*ściezka URL do obrazka*/; 
                   /*Tworzenie wątku*/ 
                   pobieranieMapkiThd*pMapaT=new pobieranieMapkiThd(true); 
                   pMapaT->setThreadData(strULR ,m_pImage/*wskaźnik do obrazka TImage*/,i,j); 
                    pMapaT->Resume();  
              } 
      } 
} 

no i teraz wątek pobierajacy obrazki

void __fastcall pobieranieMapkiThd::Execute() 
{ 
        TPngImage *pPng = new TPngImage(); 
        TMemoryStream *pPicStream = new TMemoryStream(); 
        TIdHTTP* idhTmp=new TIdHTTP(0); 

        idhTmp->Get(m_strPath,pPicStream);//pobranie obrazka 
        pPicStream->Seek(0,0); 
        pPng->LoadFromStream(pPicStream)  ;//zapis obrazka do zmiennej 
        m_pImage->Canvas->Lock(); 
        m_pImage->Canvas->Draw((m_isposX)*256, (m_isposY)*256, pPng ); 
        m_pImage->Canvas->Unlock(); 
} 

wszystko działa - ale co najwyżej średnio

jak widać jeden obrazek top jeden wątek - nie wiem czy to dobrze, czy źle - na pewno szybko

problemem sa białe plamy na rysunku pewnie spowodowane blokowaniem obrazka (m_pImage->Canvas->Lock();

jeśli przeniosę to do osobnej funkcji i dam Synchronize(funkcja) białych plam nie ma, ale trwa to kilka sekund

jako, że jak na razie zupelnie się na tym nie znam to nie wiem czy robię to dobrze czy źle
mam taki plan, żeby obrazki zapisywać do tablicy - a na końcu je wczytać do obrazka

nie wiem też czy sposób, aby wczytanie każdego obrazka był to osobny watek jest dobry czy zły

chodzi mi o to, aby było szybko i pewnie
teraz jest albo szybko (ale czasami sie pojawiają białe plamy) albo pewnie, czyli trwa to trochę, ale nie ma białych plam

w związku z tym mam prośbę o podanie sposobu jak to wszystko zgrać

co do pomysłu ze zbieraniem danych do tablicy a potem wyświetlaniu tej tablicy to nie wiem, czy jest dobry czy zły i co najważniejsze - kiedy i jak można się dowiedzieć, że już wątków żadnych nie ma i że można wyświetlać

0

Oj cieknie, cieknie. Tworzysz trzy obiekty i nigdzie ich nie zwalniasz. Wyjście z wątku automatycznie ich nie usunie.

Co do ilości wątków, wszystkie obrazki możesz/powinieneś ściągać w jednym, specjalnie do tego celu stworzonym wątku.

Jeśli chodzi o rysowanie po image, tylko via Synchronize.

0

dzięki za odpowiedź
to, ze cieknie to ja wiem
ale to nie jest na razie problemem - na razie chce żeby to działało - a jak daję synchronize(funkcja) to działa ale powoli - kilka, klikanaście sekund

0

W Synchronize dajesz tylko rysowanie (Draw), odbieranie obrazków pozostaje w wątku.

0
0x666 napisał(a)

W Synchronize dajesz tylko rysowanie (Draw), odbieranie obrazków pozostaje w wątku.

dzięki za odpowiedź - motam się z tym, co prawda działa, niby jest OK, ale jako, że nie potrafię zweryfikować czy to co zrobiłem jest dobre słuszne poprawne - napiszę co zrobiłem, jak ktoś będzie miał chęć ochotę może coś napisać, czy jest to dobrze, źle, może być, czy całkowicie do niczego

za uwago serdecznie dziękuję

1)w Formie na OnActivate tworzę klasę do rysowania mapek na TImage
2)tworzę wektor na watki pobierające obrazek z internetu - ich ilość to x*y
3)metoda do wywoływania wątków

void mapka::pobieranieObrazkow(int iX,int iY)
{
	int iH = getMaxDimm(m_pImage->Height);
	int iW = getMaxDimm(m_pImage->Width);

	m_pMapThreads.reserve(iH*iW);

	for(UINT i=0;i<iH*iW;i++)
	{
		mthread *pMThrd = new mthread(true);
		pMThrd->FreeOnTerminate=true;
		pMThrd->ustawObrazek(m_pImage);
		m_pMapThreads[i]=pMThrd;
	}

	int  isposX=0, isposY=0, iImg=0, iIDX=0;
	UnicodeString strPath;
	do{
		  do{
				strPath = "url do mapki";
				m_pMapThreads[iIDX]->ustawDaneWatku(strPath,isposX,isposY);
				 m_pMapThreads[iIDX]->Resume();
				 iIDX++;
				}while(++isposY<iW );
				 isposY=0;
		  }while(++isposX<iH );
}

4)metody wątku Execute i ryoswanie

void __fastcall mthread::Execute()
{
	//---- Place thread code here ----

	TPngImage *pPng = new TPngImage();
	TMemoryStream *pPicStream = new TMemoryStream();
	TIdHTTP *idhTmp = new TIdHTTP(NULL);
	idhTmp->Get("http://"+m_strPath,pPicStream);//jak przesyłałem z http to mi się tu wykrzaczało
	pPicStream->Seek(0,0);
	pPng->LoadFromStream(pPicStream);
	m_pBmp = new Graphics::TBitmap;
	m_pBmp->Width = 256;
	m_pBmp->Height = 256;
	m_pBmp->Canvas->Draw(0,0,pPng);
	Synchronize(rysuj);
}

void __fastcall mthread::rysuj()
{
	if(m_pImage->Canvas->LockCount)
	{
	   WaitForSingleObject(m_pImage,1000);
	}
	else
	{
	   m_pImage->Canvas->Lock();
	   m_pImage->Canvas->Draw(m_iX*256,m_iY*256,m_pBmp);
	   m_pImage->Canvas->Unlock();
	}

}

działa dobrze - nie ma białych plam - wygląda, że jest OK, ale czy tak jest tego na 100% pewien nie jestem

ps - takie pytanie gdzie w Builderze można zobaczyć czy są wycieki pamięci czy nie, w VS w sekcji (bodajże) output jesli cos nie tak jest napis - Detect Memory Leak i tam dalej co tam trzeba było napisane
czy tutaj też jest w sekcji output to widoczne?bo nie widzę czegoś takiego w output nawet gdy specjalnie new ustawie, a o delete zapomnę</cpp>

0

jeszcze jedno

wreszcie zrozumiałem, skąd białe plamy

otóż to

  idhTmp->Get("http://"+m_strPath,pPicStream);//jak przesyłałem z http to mi się tu wykrzaczało

jest wywoływane jakby asynchronicznie - i jak zdąży wię wykonać przed przejściem do nastepnej instrukcji to OK jak nie to biała plama

tylko teraz pytanie co lepiej

dać to do metody OnEndWork
czy dać to w metodzie rysuj która jest synchronizowana?

0

wygląda, że jest OK, ale czy tak jest tego na 100% pewien nie jestem

No OK nie jest, bo dalej masz ten wyciek. Nie wiem po co w rysuj są te akcje z lock'ami, przecież metoda ta wywoływana jest w kontekście głównego wątka i synchronizacja nie jest potrzebna. Po co kopiujesz do m_pBmp zawartość pPng? Nie możesz po prostu przekazać wskaźnik pPng do rysuj?

Z WaitForSingleObject to przegiąłeś maksymalnie... ;/

takie pytanie gdzie w Builderze można zobaczyć czy są wycieki pamięci czy nie (...)

W CB jest bodajże CodeGuard od tego typu rzeczy.

(...) jest wywoływane jakby asynchronicznie

Dziwne, bo nic w dokumentacji na ten temat nie ma. Przechwyć wyjątek EAssertionFailed (w sumie powinieneś to zrobić) i zobacz jaka jest jego treść, może dowiesz się jakichś szczegółów.

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