Thread, Datenzugriff und WindowsForms Anwendung



  • Hallo Leute,
    bei der Verwendung eines Thread innerhalb einer WindowsForms Anwendung bin ich auf eine mir unerklärliche Problematik gestoßen. Um die Problematik näher zu untersuchen, habe ich mal ein kleines Testprogramm gebaut, bei dem der Thread über button1 gestartet und über einen weiteren button2 gestoppt werden kann. Hierfür ist in der Klasse „Form1“ eine boolesche Variable „Stop“ vorgesehen. Wenn die Variable auf „true“ steht, stoppt der Thread automatisch. Zur Verdeutlichung des Sachverhaltes hier zunächst ein wenige Code:

    public ref class Form1 : public System::Windows::Forms::Form
    	{
    	public:
             static System::Threading::Thread ^GenGraph;
             static bool Stop;	
    	//sonstiges
             void button1_Click(System::Object^  sender, System::EventArgs^  e);
             void GraphPaint ();
             void button2_Click(System::Object^  sender, System::EventArgs^  e);
             };
    public ref class ABC : public Form1 
    	{
    	private: 
    	double a;
    	double b;
    	double c;
    	public:
    	   ABC() {
    		a = 0;
    		b = 0;
    		c = 0;
                      }	
    	ABC(double a1, double b1,double c1) {
    		a = a1;
    		b = b1;
    		c = c1;
    	}
    
    	ABC^ setabc(double a1, double b1, double c1){	
    			return gcnew ABC(a = a1, b = b1, c = c1);
    	}
    };
    
    void Form1::button1_Click(System::Object^  sender, System::EventArgs^  e) {
       Stop = false;
       GenGraph = gcnew System::Threading::Thread(gcnew  ThreadStart(this,&Form1::GraphPaint));
       GenGraph->Start();
    }
    
    void Form1::button2_Click(System::Object^  sender, System::EventArgs^  e) {
    Stop = true;
    }
    
    void Form1::GraphPaint() {
    
    		ABC^New1 = gcnew ABC;
    			while(!Stop) {
    				New1->setabc(0,0,0);
    				Sleep(10);
    }
    }
    

    Dieser Mechanismus funktioniert auf einem win7 64bit System solange, bis man die Sleep- Anweisung auskommentiert. Mit auskommentierter Sleep Anweisung lässt sich der Thread dann nicht mehr beenden, obwohl stop auf true steht. Auf einem XP SP3 32bit System funktioniert der „stop“ Mechanismus nur, wenn man alle Zugriffe auf das ABC- Objekt komplett auskommentiert.
    Das stop – bool war jetzt ein Beispiel, um zu testen, wann der Zugriff auf Daten versagt. Genauso hätte an diese Stelle auch ein- oder mehrere Arrays treten können.
    Gibt es denn eine Möglichkeit, um aus dem Thread heraus eine sichere Abfrage von Daten durchzuführen?

    MfG



  • Benutze korrekte Mittel zur Inter-Thread Kommunication, z.B. System::Threading::ManualResetEvent.



  • Hallo theta,
    vielen Dank für Deinen Rat. Angesichts der für .net –Threadsteuerung erforderlichen komplexen Syntax habe ich dann doch noch ein bisschen mit dem Testprogramm herumexperimentiert. Offensichtlich verursacht in:

    public ref class ABC : public Form1
    

    das Schlüsselwort:

    public Form1
    

    ein Problem. Ich habe es daher einfach mal entfernt und erstaunlicherweise festgestellt, dass nun der threadbasierte Zugriff auf in der Klasse Form1 sowie ABC gespeicherte Daten problemlos funktioniert.

    MfG.



  • 7x7-7 schrieb:

    Offensichtlich verursacht in:

    public ref class ABC : public Form1
    

    das Schlüsselwort:

    public Form1
    

    ein Problem.

    1. nur public ist ein Schlüsselwort
    2. Form1 ist hier die Klasse von der die Klasse ABC ableitet (Vererbung)
    ➡ ABC leitet von Form1 ab

    Interessant wäre jetzt natürlich welches Problem entsteht. Ich vermute mal ganz einfach, Du versuchst von dem nicht UI Thread ein UI Element zu ändern, was zu einer Exception führt.

    7x7-7 schrieb:

    Ich habe es daher einfach mal entfernt und erstaunlicherweise festgestellt, dass nun der threadbasierte Zugriff auf in der Klasse Form1 sowie ABC gespeicherte Daten problemlos funktioniert.

    1. Das löst wohl kaum dein Problem
    2. Nur weil Du denkst, dass es funktioniert (- auch wenn Du denkst dass Du siehst, dass es funktioniert), heisst das noch lange nicht dass es funktioniert - gerade bei Threading. Du solltest dein Code mit "theoretischem" Wissen untermauern (Du musst wissen, warum was wie getan werden muss - da hilft die Doku).

    Alles in Allem scheint mir, dass Du nur wenig Erfahrung mit Programmierung hast. Da ist Threading ein allgemein schwieriges Thema und vorallem hast Du dafür definitiv die falsche Sprache (C++/CLI) ausgewählt. Nimm C# oder C++ oder Java, oder Python..., aber nicht C++/CLI. Siehe hier.

    Simon



  • Hallo Simon,

    danke für die ausführliche Doku – ich war ganz froh, dass mein Progrämmchen bis heute erstmal so tut, als ob es funktionieren würde. Schließlich zeigt es mir grafisch Daten an, die aus einer Datenakquisitionshardware von einer Analogquelle akquiriert werden, die ich zum Vergleich auch an ein Oszilloskop angeschlossen habe. Ca. 300000 Datenpunkte werden dafür von einem 1.Thread alle 100 ms umgedreht, um 500 ausgewählte Werte in ein int-Array zu schreiben, dass in der Klasse „Form1“ gespeichert ist. Der 2. Thread greift ebenfalls asynchron auf dieses Array zu, um die enthaltenden Daten als Kinetik in einer picturebox als Pixelgrafik darzustellen. Das ABC Objekt ist in Wirklichkeit ein Vektor, der wesentlich auf Deinem Support vom 26.09.2008 basiert. Mit dem Vektor werden in diesem 2.Thread Pixel zwischen zwei Datenpunkten interpoliert, um eine quasikontinuierliche Datendarstellung zu erzeugen. Das "public: Form1" schien mir aufgrund von „Objektorientiertes Programmieren in C++ “ von Nicolai Josuttis 1995 Seite 284 an der gegebenen Stelle gerechtfertigt.

    Das Ergebnis meines kleinen Experimentes fand ich interessant, weshalb ich es hier mal mitgeteilt habe.

    Den verlinkten Beitrag, sowie den Blog von JK habe ich schon ausführlich angeschaut – vielleicht hat er ja Recht. Jedenfalls fände ich es schade, wenn es zukünftig kein C++/CLI mehr geben würde.

    MfG.


Log in to reply