Multithreading

rainer82

Grünschnabel
Hi,

Ich moechte gerne eine std::vector an meinen erzeugten "Working Thread" weitergeben. Wie wandle ich den std::vector in LPVOID um?
Kann man es wirklich nicht casten? Der std::vector wird in einer Klasse CFileList erzeugt. In der Dialogklasse arbeite ich alle, zuvor initialisierten, Vektorelemente (Dateien) ab und es funktioniert ohne Probleme.
Code:
oid CImg2Dlg::OnBnClickedROI()
{
	SetTimer(1,400,NULL);
	m_StartTime=CTime::GetCurrentTime();

	int width,height;
	if(m_Format.GetCurSel()==F512)
		{
			width=height=512;
		}
	else{
			width=648;
			height=572;
		}
	std::vector<ImgElement>::iterator listIte;
	char* data=new char[width*height];

	int count=0;
	for(listIte=m_fList.ImgList.begin();listIte!=m_fList.ImgList.end();++listIte)
		{	
			
			m_gpData.LoadFile((*listIte).name);

			if(!m_ROI.FindROI(width,height))(*listIte).blink=true;
			data=0;
			delete[] data;
		}
	
	m_StopTime=CTime::GetCurrentTime();
	m_ElapsedTime=m_StopTime-m_StartTime;
	SetDlgItemInt(IDC_MIN,m_ElapsedTime.GetMinutes(),FALSE);
	SetDlgItemInt(IDC_SEC,m_ElapsedTime.GetSeconds(),FALSE);
	KillTimer(1);
}

Nun passiert in dieser for-Schleife eine ganze Menge Bildverarbeitung mit hohem Zeitanspruch. Moechte fuer den Benutzer den Dialog freigeben und auch die Darstellung waehrend der Bildverarbeitungsroutine aendern.
Portiere ich die Bildverarbeitung in eine von CWinThread abgeleiteten Klasse, ist das zuvor geladene Vektorobjekt leer.
Code:
BOOL CCompute::InitInstance()
{
	std::vector<ImgElement>::iterator listIte;
	int szco=0;
	for(listIte=m_fList.ImgList.begin();listIte!=m_fList.ImgList.end();++listIte)
		{	
			m_Processor.LoadFile((*listIte).name,width,height);
			m_Processor.DoFFT(width,height);
			m_Processor.Filter(width,height);
			m_Processor.Threshold(width,height);
			m_Processor.MorphOperation(width,height);	
		}
	return TRUE;
}

Warum ist meine Liste hier leer? Und wie kann ich an an InitInstance() Parameter uebergeben? Wenn ich ein CCompute Objeket in einer anderen Klasse erzeuge? Es kommt die Fehlermeldung: error C2248: 'CCompute::CCompute' : cannot access protected member declared in class 'CCompute' bei diesem Versuch.

Fuer Kritik, Beispielcodes, Literaturhinweis, Ratschlaege waehre ich sehr dankbar!

Gruss Rainer
 

deepthroat

Erfahrenes Mitglied
Hi.
Ich moechte gerne eine std::vector an meinen erzeugten "Working Thread" weitergeben. Wie wandle ich den std::vector in LPVOID um?
C++:
static_cast<void*>(&a_std_vector);
Du mußt natürlich sicherstellen, das der Vektor nicht gleichzeitig von mehreren Threads bearbeitet wird.
Code:
	char* data=new char[width*height];

	int count=0;
	for(listIte=m_fList.ImgList.begin();listIte!=m_fList.ImgList.end();++listIte)
		{	
			
			m_gpData.LoadFile((*listIte).name);

			if(!m_ROI.FindROI(width,height))(*listIte).blink=true;
			data=0;
			delete[] data;
		}
Warum löscht du data innerhalb der Schleife? Warum machst du das bei jedem Durchlauf? Wenn der Vektor leer ist wird der Speicher nicht freigegeben.
Portiere ich die Bildverarbeitung in eine von CWinThread abgeleiteten Klasse, ist das zuvor geladene Vektorobjekt leer.

Code:
BOOL CCompute::InitInstance()
{
	std::vector<ImgElement>::iterator listIte;
	int szco=0;
	for(listIte=m_fList.ImgList.begin();listIte!=m_fList.ImgList.end();++listIte)
		{	
			m_Processor.LoadFile((*listIte).name,width,height);
			m_Processor.DoFFT(width,height);
			m_Processor.Filter(width,height);
			m_Processor.Threshold(width,height);
			m_Processor.MorphOperation(width,height);	
		}
	return TRUE;
}

Warum ist meine Liste hier leer? Und wie kann ich an an InitInstance() Parameter uebergeben? Wenn ich ein CCompute Objeket in einer anderen Klasse erzeuge? Es kommt die Fehlermeldung: error C2248: 'CCompute::CCompute' : cannot access protected member declared in class 'CCompute' bei diesem Versuch.
Ohne den Code zu sehen, kann man da nicht viel sagen.

Gruß

PS: Warum kreierst du denn eigentlich einen User Interface Thread? Eigentlich möchtest du doch einen Worker Thread, oder? http://msdn.microsoft.com/en-us/library/69644x60(VS.80).aspx
 
Zuletzt bearbeitet:

rainer82

Grünschnabel
Vielen Dank fuer die Hinweise. Hab es jetzt heraus bekommen. This Pointer sei Dank! Mit dem Pointer habe ich Zugriff auf alle Memberfunktionen und -variablen meiner Dialogklasse.

Starten des Threads aus einem meiner Eventhandler in der Dialogklasse:
Code:
AfxBeginThread(WorkingThread,this,THREAD_PRIORITY_NORMAL,0,0,NULL);
wobei WorkingThread so in der Headerdatei meiner Dialogklasse deklariert werden muss.:
Code:
class CProImg2Dlg : public CDialog
{
// Construction
public:
	static UINT WorkingThread(LPVOID Param);
Und so sieht dann der zugehoehrige Body aus:
Code:
UINT CProImg2Dlg::WorkingThread(LPVOID CDlgObj)
{	
	CProImg2Dlg	*this_dlg=(CProImg2Dlg*)CDlgObj; 
	std::vector<ImgElement>::iterator listIte;
	int width=this_dlg->width;
	int height=this_dlg->height;

	for(listIte=(this_dlg->m_fList.ImgList.begin());listIte!=this_dlg->m_fList.ImgList.end();++listIte)
		{	
			if(this_dlg->m_ROI.FindROI((*listIte).name,width,height))
				{
					(*listIte).blink=false;	//ROI detected -> no eye blink 
				}
		}
	this_dlg->KillTimer(1);
	return TRUE;

Soviel zu dieser Huerde. Naechste Sache ist, wie komme ich von aussen an die bereits verarbeiteten Vectorelemente heran? Ich darf ja nicht in den Thread eingreifen. Wie kann ich den Thread von aussen stoppen?
PS: Warum kreierst du denn eigentlich einen User Interface Thread? Eigentlich möchtest du doch einen Worker Thread, oder? http://msdn.microsoft.com/en-us/libr...8VS.80).aspx
Weil ich relativ neu in so ziemlich Allem bin, noch keine Ahnung habe und beide Varianten betrachten moechte. Von der Strucktur gefaellt mir die UI Thread Geschichte besser, weil sie in einer extra Klasse erzeugt werden muss.
Ich will lernen, also immer her mit Meinungen und Ratschlaegen!

Gruss Rainer
 
Zuletzt bearbeitet:

rainer82

Grünschnabel
Ich habe jetzt meine Threadroutine in einer neuen Klasse abgelegt. Nun moechte ich das resultierende Bild auf dem Picturecontrol meines Hauptdialoges darstellen. Wie greife ich, aus meinem Thread, auf Funktionen wie z.B. OnPaint() zu? Kann ich mir ein HANDLE aus dem Hauptdialog holen mit GetParent()? Wenn das geht, wie und ist das eine elegante, unanfaellige Loesung? Habe bisher keine passenden Referenzen gefunden.

Gruss
 
Zuletzt bearbeitet: