Laden...

Forms und Threading - Grundsatzproblem

Erstellt von Gawan vor 16 Jahren Letzter Beitrag vor 16 Jahren 1.810 Views
G
Gawan Themenstarter:in
38 Beiträge seit 2005
vor 16 Jahren
Forms und Threading - Grundsatzproblem

Hallo zusammen,

ich möchte mir mittels Threading und Forms eine Applikation basteln die im Hintergrund Daten aus einer Datenbank ausliest und in der Form in ein Textfeld schreibt OHNE dass während des Auslesevorganges die Applikation einfriert (deshalb Threading).

Ich habe mir deshalb also eine Form mit einer richtextBox gebastelt und ein Delegate daraufgesetzt um von außen zugreifen zu können:


public delegate void UpdaterichTextBox1Callback(string text);

        private void UpdaterichTextBox1Label(string text)
        {
            richTextBox1.Text+=text;
        }
        public void UpdaterichTextBox1(string text)
        {
            if (InvokeRequired)
                BeginInvoke(new UpdaterichTextBox1Callback(UpdaterichTextBox1Label), new object[] { text });
            else UpdaterichTextBox1Label(text);
        }

Dann habe ich in meinem Hauptprogramm eine Instanz dieser Form und einen Thread erstellt mit denen ich arbeiten will.


static Form1 fm1 = new Form1();
private static Thread th1; 

Jetzt starte ich die Applikation, aktiviere die Form und starte einen Thread der mir alle paar Sekunden etwas in die Textbox schreiben soll.


Application.Run(fm1);
th1 = new Thread(new ThreadStart(FormRun));

static void FormRun()
{
fm1.UpdaterichTextBox1("Schreib was rein");
System.Threading.Thread.Sleep(time*1000);
}

Wenn ich das ausführe wird zwar die Form geladen, der Thread th1 wird allerdings nicht mehr ausgeführt, was mich mittlerweile schon in den Wahnsinn treibt 🙂🙂

Hat da vllt. jemand einen Tip für mich ?

Danke
Gawan

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo Gawan,

wo startest du denn den Thread? In dem Code den du gepostest hast, erzeugst du ihn nur, startest ihn aber nicht.

herbivore

1.985 Beiträge seit 2004
vor 16 Jahren

Hallo Gawan,

Application.Run(fm1);
th1 = new Thread(new ThreadStart(FormRun));

Die beiden Zeilen können nicht das machen, was Du möchtest, da beim Application.Run(fm1) die Ausführung stehen bleibt. Deswegen wird das Fenster angezeigt, der Thread aber nicht erstellt.

Ausführen musst Du den Thread auch noch. Ich kann kein .Start() entdecken.

Gruß,
Fabian

"Eine wirklich gute Idee erkennt man daran, dass ihre Verwirklichung von vornherein ausgeschlossen erscheint." (Albert Einstein)

Gefangen im magischen Viereck zwischen studieren, schreiben, lehren und Ideen umsetzen…

Blog: www.fabiandeitelhoff.de

G
Gawan Themenstarter:in
38 Beiträge seit 2005
vor 16 Jahren

Hallo ihr beiden,

ja das ist schon richtig, aber ich kann ja den Thread - der ins Form schreiben soll - nicht starten bevor das Form mit Application.Run gestartet wurde 🙂

Das ist auch mein Verständnisproblem im Moment ?(

Danke

Gawan

1.985 Beiträge seit 2004
vor 16 Jahren

Hallo Gawan,

das stimmt schon, aber Du kannst den Thread doch im Form starten oder nicht? Dann ist das Form auf jeden Fall da.

Evtl. in das FormLoad-Event, damit es keine Probleme mit dem Fenster-Handle gibt.

Gruß,
Fabian

"Eine wirklich gute Idee erkennt man daran, dass ihre Verwirklichung von vornherein ausgeschlossen erscheint." (Albert Einstein)

Gefangen im magischen Viereck zwischen studieren, schreiben, lehren und Ideen umsetzen…

Blog: www.fabiandeitelhoff.de

G
Gawan Themenstarter:in
38 Beiträge seit 2005
vor 16 Jahren

Hm... ja, das hab ich mir auch schon überlegt, aber das würde ja heißen, dass ich im Form eine Instanz meiner Hauptklasse aufrufen muss um den darin angelegten Thread zu starten ??

Das sieht mir dann irgendwie nach endlosverkettung aus ..... Hauptprogramm lädt Instanz der Form -> Form lädt Instanz des Hauptprogrammes ....

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo Gawan,

dann starte ihn vor Application.Run und lass ihn an einer roten Ampel warten, bis das Form soweit ist und die Ampel auf grün setzt. Siehe Consolenanwendung mit Timer optimieren [Semaphore/Ampel]

herbivore

G
Gawan Themenstarter:in
38 Beiträge seit 2005
vor 16 Jahren

Ok. ist mir soweit alles klar ... ABER wann ist die Form "soweit" ?
Wenn ich den Code debugge komme ich genau bis
Application.Run(fm1);
da öffnet sich die Form, ich kann mit ihr interagieren, aber es wird kein neuer Code mehr ausgeführt

L
333 Beiträge seit 2007
vor 16 Jahren

Z.B. im Form.Load-Ereignis, wenn das aufgerufen wurde, kannst du auch mit dem Form arbeiten. Ich hab mir die angegebenen Beispiele nicht angeschaut, aber im Form_Load müsstest du halt irgendwie signalisieren, dass dein anderer Thread jetzt machen darf.

Dass du über Application.Run nicht debuggen kannst, ist klar, da Application.Run ja die gesamte Message Loop enthält, die logischerweise erst dann beendet wird, wenn das Hauptfenster geschlossen wird.

Warum brauchst du überhaupt Code, bevor die Application gestartet wurde? Ich hab da nie mehr als ein paar Zeilen Konfiguration hingeschrieben, der Rest lief immer innerhalb des Fensters oder darin gestarteter Methoden.

G
Gawan Themenstarter:in
38 Beiträge seit 2005
vor 16 Jahren

Du meinst ich kann also die gesamte Datenverwaltung (=Lesen aus der Datenbank) und das dazugehörige threading in der Form-Klasse machen ??

d.h. in der Anwendung selbst starte ich nur noch die Form - den Thread und die gesamte Logik packe dann dort rein

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo Gawan,

ja

herbivore

L
333 Beiträge seit 2007
vor 16 Jahren

Genau. Üblicherweise macht man das in GUI-Anwendungen so. Zumindest unter Windows. Unter Linux scheinen Dinge etwas anders zu laufen, da weiß ich aber nix genaues.

B
171 Beiträge seit 2007
vor 16 Jahren

Servus,

und änder mal


richTextBox1.Text+=text;

um in :


richTextBox1.AppendText(text);

Gruß
Budi

Nimm das Leben nicht zu ernst - denn du kommst nicht lebend raus!

G
Gawan Themenstarter:in
38 Beiträge seit 2005
vor 16 Jahren

Hallo zusammen,

ich hab das ganze Paket jetzt mal umgebaut:

Hauptprogramm:


class CheckFolder
    {
        static Form1 fm1 = new Form1();
        private static bool active = false;

        [STAThread]
        static void Main()
        {
            Application.Run(fm1);
            fm1.Close();
        }

    }

Code in der Form:


public Form1() {
            InitializeComponent();
        }

private void InitializeComponent()
		{
...
}
private void Form1_Load(object sender, EventArgs e) {
            th1 = new Thread(new ThreadStart(FormRun));
            th1.Start();
        }

        private void FormRun()
        {
            //  Schreiben in die RichTextBox per Delegate ...
        }


Das klappt soweit auch ganz gut, ABER wenn ich vor dem Schreiben in die Box z.B. einen 10 sec-Timeout einbaue, dann bleibt die gesamte Form "stecken" und ich kann in der Zeit nichts damit machen.
Aus meiner Sicht sollte ja der Thread dazu da sein, dass ich machen kann was ich will, ohne dass die Form davon belästigt wird !?

lG
Gawan

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo Gawan,

[FAQ] Warum blockiert mein GUI?

herbivore

L
333 Beiträge seit 2007
vor 16 Jahren

Das tut zwar nichts zu deinem beschriebenen Problem, aber diese Zeile solltest du entfernen:

fm1.Close();

Die wird erst erreicht, wenn das Fenster bereits geschlossen ist. Was passiert, wenn man sie ein zweites Mal aufruft, kann ich nicht sagen. Bevor du die Innereien deines Programms umbaust, bietet es sich an, ein neues Projekt zu erzeugen und mal anzuschauen, wie die Dinge so aussehen sollten. Das kann man dann auf seine eigenen Anwendungen übertragen, wenn man es mal verändert hat und nicht weiß, wie es vorher war.

Das Blockieren des GUI kann ich mir aufgrund deiner Codebeschreibung nicht erklären.