Thread übergreifender Zugriff auf Controls

Fridulin

Erfahrenes Mitglied
Hallo,

ich habe folgendes Problem in meinem C# Programm. Ich führe in meiner MainForm ein Thread in einer Klasse aus.
Code:
verbinden_Tread = new Thread(Klasse_Verbindung.verbinden_thread);
In der Funktion verbinden_thread möchte ich bei einem Fehler eine Funktion in der MainForm ausführen.
Code:
Main_Form.fehler("Leider leider, trat folgender Fehler auf: \n\n" + ex.Message);
in der MainForm Funktion „fehler“ kann ich nun allerdings keine TextBox mehr ändern oder sonst etwas in der Form, nur MessageBox klappt noch. Also textbox.text = „text“; funktioniert alles nicht mehr, es erscheint allerdings auch kein Fehler, es wird nur nichts in der Form geändert.

Ich gehe davon aus das es nur ein kleiner Fehler meiner seits ist, aber ich komme einfach nicht darauf.
Falls jemand eine Idee hat würde ich mich sehr freuen.

Vielen Dank im Vorraus.
Fridulin


Edit: Invoke hab ich auch schon eingebaut, bringt allerdings auch nichts.
 
Zuletzt bearbeitet:
Hallo Fridulin,

also Invoke ist schon mal der richtige Weg für GUI-Aktualisierungen aus einem anderen Thread heraus. Zeige doch mal die Methode "Main_Form.fehler()".

Gruß
MCoder
 
Hallo,

vielen Dank für die Antwort.

Also die Funktion „fehler“:
Code:
private delegate void delegate_krams(string nachricht);

public void fehler(string nachricht)
{
	if(this.InvokeRequired)
        	{
		MessageBox.Show("ini");
		this.Invoke(new delegate_krams(fehler), new object[]{nachricht});
        	}
        	else
        	{
		empfange(nachricht);
		MessageBox.Show("dd");
		rtb_nachricht.Text = "sdd\n adsdas";
        		//MessageBox.Show("asdasd" + nachricht);
        		tb_name.Text = "ddssssssssss";
        		l_ueberschrift.Text = "asdddddddd";
        	}
}

Viele Grüße
Fridulin
 
Hallo Fridulin,

probiere mal, Invoke nicht für die Form sondern nur für das zu ändernde Control zu verwenden.

Gruß
MCoder
 
Hi Mcoder,

hast du? vielleicht ein Codebeispiel? Ich hatte das bis jetzt nur mit der Form angewandt.

Viele Grüße und vielen Dank
Fridulin


Edit: Ich konnte es jetzt Testen, hat aber auch nicht geklappt. Invoke wird nicht benötigt, er geht garnicht in die If Schleife.
Code:
if (rtb_nachricht.InvokeRequired)
{
        			
        	rtb_nachricht.Invoke(new MethodInvoker(delegate(){fehler(nachricht);}));
	return;
}
rtb_nachricht.Text = "sdd\n adsdas";
 
Zuletzt bearbeitet:
Hallo Fridulin,

finde ich schon seltsam, dass die Controls nicht aktualisiert werden. Probiere mal, ob ein DoEvents() was ändert:
C#:
...
rtb_nachricht.Text = "sdd\n adsdas";
Application.DoEvents();
...
Wenn ja, scheint noch irgendeine Aktion den GUI-Thread zu bremsen.

Gruß
MCoder
 
Hi,

leider hat das auch keinen Erfolg.

Ich hatte bis jetzt auch nie Probleme damit und Invoke hat immer seinen Dienst getan. Das einzigste was ich neu gemacht habe und vorher noch nicht hatte ist, daß der Thread in einer Klasse welche sich in einer anderen Datei befindet gestartet wird und ich in der Klasse direkt etwas in der MainForm ändern möchte. Sonst hab ich mit return gearbeitet in der Klasse um etwas in der MainForm zu ändern. Aber das erklärt ja nicht, wieso das mit einmal nicht mehr geht.

Vielleicht hast du ja noch eine Idee.

Viele Grüße
Fridulin
 
Wie kennt die andere Klasse die MainForm, übergibst du ihr eine Referenz? Was meinst du mit " Sonst hab ich mit return gearbeitet..."?

Gruß
MCoder
 
Hi,

sonst hab ich einen neuen Thread in der MainForm gestartet und zum Beispiel, wenn ich ein Rückgabewert der Klasse haben möchte „string bla = einstellungenbearbeiten.einstellungen_einlesen("bla");“

Nun läuft mein Programm folgendermaßen ab:
In ein Click Event (Button) wird ein Thread gestartet(Thread ist Global deklariert), welche Funktion in der Klasse sitzt.
Code:
Thread Verbinden_Tread;
void Btn_verbindenClick(object sender, EventArgs e)
{
	klasse_verbindung Klasse_Verbindung = new klasse_verbindung();
	rtb_nachricht.Text ="Ich versuche eine Verbindung herzustellen, bitte warten\n\n";
	Verbinden_Tread = new Thread(Klasse_Verbindung.verbinden_thread);
	Verbinden_Tread.Start("test|test_user|#tester|192.168.1.2|6667");
}
Die Funktion in der Klasse, habe ich nun gekürzt das nur wieder die HauptForm aufgerufen wird und etwas übergeben wird.
Code:
MainForm Main_Form = new MainForm();
public void verbinden_thread(object obj_daten)
{
	Main_Form.fehler("Leider leider, trat folgender Fehler auf: \n\n" + "ex.Message");
}
So und die Funktion in der MainForm „fehler“ kennst du ja bereits.

Viele Grüße
Fridulin
 
Hallo Fridulin,

mit MainForm Main_Form = new MainForm(); erzeugst du eine neue Instanz von MainForm, die mit dem schon vorhandenen Fenster nichts zu tun hat.
Du müsstest stattdessen der Klasse "klasse_verbindung" einen Parameter zum aktuellen MainForm übergeben:
C#:
// klasse_verbindung

public class klasse_verbindung
{
    private MainForm Main_Form;
    
    public klasse_verbindung(MainForm Main_Form)
    {
        this.Main_Form = Main_Form;
    }
    ...
}

// MainForm

void Btn_verbindenClick(object sender, EventArgs e)
{
	klasse_verbindung Klasse_Verbindung = new klasse_verbindung(this);
	...
}
Gruß
MCoder
 

Neue Beiträge

Zurück