AfxBeginThread/Zugriff auf Variablen

michizn

Grünschnabel
Hallo zusammen,

ich habe ein Problem beim Zugriff auf eine Variable vielleicht kann mir einer auf die Sprünge helfen.Erstmal ich programmiere mit Visual Studio 2003 in C++ mit MFC.

Das gesamte Programm besteht aus einer größeren Benutzeroberfläche wo über Schlatflächen und Buttons gewisse Funktionen und Routinen gestartet werden. Hierbei soll u.a. mit einem START Button eine Schleife gestartet werden, die vom COM Port einen String einlesen, konvertieren und aufgeteilt in 2 EditControl Feldern im GUI ausgeben soll (es handelt sich dabei schlicht um einen Winkelsensor der Abweichungen in 2 Achsen misst und in einer Zeichenkette gepackt an die Schnittstelle schickt). Das einmalige Auslesen des Ports und die Ausgabe in den Feldern ist ja kein Problem allerdings soll dieses Auslesen und Ausgeben solange gemacht werden bis auf einen STOPP Button gedrückt wird (daher die Schleife). Ich habe jetzt mal versucht (für mich das erste Mal) die Schleife in einem eigenen Thread starten zu lassen, um überhaupt den Button fürs Beenden der Schleife drücken zu können, dass hat soweit auch geklappt.

Start Thread:
Code:
 ... AfxBeginThread(getaxis,this,THREAD_PRIORITY_NORMAL);

Aufgerufene Funktion:
Code:
UINT getaxis(LPVOID pParam) {
	while (true) {
		...
		//xaxis ausgeben
		//yaxis ausgeben
		Sleep(250);
		if(getstopcommand() == true) break;
	}
	return 0;
}

Der Start des Thread erfolgt wie erwähnt durch drücken des Start-Buttons. Die aufgerufene Funktion ist global und somit nicht in der Klasse 'CDialog' wo sich die gesamte Benutzeroberfläche befindet( ich habe allerdings die andere Variante auch ausprobiert, dass die Funktion innerhalb der Klasse als statisch deklariert wird, das Problem bleibt das gleiche). Nun das Problem: in der Funktion 'getaxis' sollen nun die Werte eingelesen und in den Feldern der Benutzeroberfläche entsprechend ausgegeben werden, hierfür ist den Feldern jeweils ein CString als Value zugeordnet. Diese Variablen sind in der CDialog Klasse deklariert und der Zugriff auf diese wird mir innerhalb der Funktion nun verwehrt:

Code:
CDialog::xaxis=MyDlg->valxaxis;

error C2597: Ungültiger Verweis auf nicht-statischen Member 'CDialog::xaxis'

Nun stellt sich mir die Frage wie ich auf diese Variablen aus der Klasse CDialog zugreifen kann bzw wie ich es schaffe immer die aktuellen Werte in den Feldern auszugeben (es muss nicht jeder einzelne Messwert sein es reicht wenn regelmäßig aktualisiert wird). Die Variablen statisch zu deklarieren funktioniert nicht ausserdem wird noch öfters auf diese zugegriffen wenn auch nicht parallel zu der laufenden Funktion. Die Messwerte einer anderen Variable zuzuordnen und ausserhalb der Schleife an die Felder zu übergeben ist auch nicht sinnvoll weil die Schleife ja vorerst nicht verlassen wird, die Felder aber einigermaßen zeitnah aktuell sein sollen. Gibt es da eventuell eine Möglichkeit dass so zu realisieren wie ich es angefangen habe oder hat jemand vielleicht eine Alternative (bin absolut kein Pro in C++ also für alles offen solang ichs versteh :) )?

recht herzlichen Dank wenn sich einer die Mühe machen sollte :)

Gruß Michi

P.S. ich hatte mal wo gelesen dass man den this Zeiger als pParam übergeben kann um eben auf Funktionen und Variablen der Klasse zugreifen zu können deshalb übergebe ich in meinem Beispiel auch den 'this' Zeiger allerdings wenn ich dann innerhalb der Funktion über this-> versuche was zu finden gehts nicht. Keine Ahnung ob mir das allgemein weiterhilft aber vielleicht hat zumindest jemand ne Erklärung was ich da falsch mache.
 
Ich nehme mal an, der Thread wird von einer Methode des Dialogs gestartet und der Thread soll seinerseits Zugriff auf die Daten des Dialog haben.

Der Fehler ist erst mal folgendes:

Code:
CDialog::xaxis=MyDlg->valxaxis;
Du verwendest die Schreibweise für statischen Memberzugriff einer Klasse.
Statisch bedeutet soviel wie: gemeinsame Daten aller Objekte eines bestimmten Types.

Kurzes Beispiel:

Code:
class A {
public:
    int a; // nicht statisches Member
};

class B {
public:
    static int b; // statisches Member
};
Die Instanzierung:

A a1;
A a2;

Wenn ich jetzt
a1.a = 5;
schreibe, steht in a2.a nicht 5, da dieses Objekt seine eigenen Daten besitzt.

B b1;
B b2;

b1.b = 5;

Hier sieht das anders aus. Da b als statisches (also gemeinsames Member) deklariert wurde, teilen sich die beiden Objekte b1, und b2 das Member b.
Demzufolge steht in b2.b jetzt ebenfalls der Wert 5!

Da die Schreibweise auf b nicht die tatsächliche Verwendung verdeutlicht, existiert für statische Member eine spezielle Schreibweise:

Klassenname::Membername

Da sich ja ALLE Objekte das Member "b" teilen, kann ich auch B::b schreiben oder eben auch b1.b oder b2.b - ist alles das gleiche.

Ganz anders bei Klasse A. Da hat jedes Objekt seine Daten.
Die Schreibweise A::a ist hier nicht erlaubt, da es keine Pauschalisierung für das Member geben darf. a1.a ist dagegen eine genaue Aussage:
Greife auf Objekt a1 und dort auf sein Member a zu.

Du schreibst:
CDialog::xaxis=MyDlg->valxaxis;

Der Kompiler MUSS annehmen, du hast für die Classe CDialog ein statisches Member vereinbart "xaxis" und möchtest jetzt den Wert zuweisen. Dem ist natürlich nicht so!
Du wirst wohl kaum den Quellcode der Klasse CDialog bearbeitet haben ;).


Sollte Dein Thread noch auf den Dialog zugreifen müssen meld Dich noch mal, da gibts recht kurze Hilfestellungen aber vielleicht hat es sich ja erübrigt.

Gruß René
 
Hallo,

dein P.S. enthält schon den richtigen Lösungsansatz, nur kannst du natürlich nicht "this" in der Thread-Funktionen verwenden. Der Parameter "pParam" enthält das Dialog-Objekt, das du nur noch entsprechend casten must:
C++:
UINT getaxis(LPVOID pParam)
{
    CMyDialog *pDlg = (CMyDialog *)pParam;
    
    pDlg->xaxis = ... ;           

    // ...
   
    return 0;
}
Heisst deine Klasse tatsächlich CDialog? Das ist doch eigentlich die Dialog-Klasse der MFC und du müstest eine davon abgeleitete Klasse haben.

Gruß
MCoder
 
Schönen guten Abend ihr beiden und gleich mal vielen Dank für die schnellen Antworten!

Natürlich habt ihr beide recht und jetz wo ichs seh versteh ichs auch war wohl einfach zu stur drin :) habs jetz so gelöst wie ihr es angedeutet habt und es lässt sich so zumindest schonmal kompilieren.. dafür also schon mal großen Dank! Jetzt hat sich ein Fehler beim Debug ergeben (also nicht beim komplieren sondern wenn man die Software auf funktionstüchtigkeit prüft kam ein Fehler nach Drücken des START Buttons) aber den Fehler werd ich mir morgen in der Arbeit etwas genauer erstmal ansehen denn der muss nicht zwingend was mit dem Code zu tun haben..

Nun hab ich aber gleich noch eine Anschlussfrage für mein Problem vielleicht könnt ihr mir da auch einen Tipp geben und zwar ist es allgemein besser einem Edit-Feld eine Variable zu geben und diese dann in so einer Schleife ständig (ca alle 300ms) zu ändern (und bewirkt das dann auch automatisch dass der Inhalt des Feldes richtig ausgegeben wird?) oder die einfachere Variante jedesmal mittels SetDlgItemText direkt ins Feld den Wert reinzuschreiben (dies benutz ich in meinem Programm öfters aber ist das auch für so schnelle Änderungen geeignet?)? ich hab mal beides ausprobiert es lies sich beides kompilieren aber bei beidem kam die gleiche Fehlermeldung beim Test deswegen kann ich nicht sagen ob überhaupt die richtigen Werte ausgebenen werden jetzt oder nicht.. falls ich den Fehler irgendwie nicht lösen kann werde ich mich dann morgen notfalls nochmal mit gernauem Wortlaut hier melden. Soweit also nochmal Danke und einen schönen Abend noch

Gruß Michi

PS @ MCoder: ne meine Klasse heisst nicht so aber ich habs ums übersichtlicher zu machen hier so umbenannt
 
Also nach meinem Verständnis sollte die Variante mit "SetDlgItemText" schneller sein, da ja das ganze DDX-Zeugs wegfällt.

Gruß
MCoder
 
Zurück