Feedback

C# - Control aus anderen Threads aktualisieren

Veröffentlicht von am 18.04.2008
(5 Bewertungen)
Jeder der schon mal mit Threads gearbeitet hat kennt das Problem: Eine länger dauernde Berechnung wird in einen Thread ausgelagert und natürlich soll der Benutzer regelmäßig über den Fortgang der Berechnung informiert werden. Das geht aber nicht aus dem Arbeitsthread, da Controls nur über den eigenen UI-Thread heraus aktualisiert werden können.
Eine Alternative ist der Backroundworker aus dem .NET-Framework. Der erhöht aber nicht gerade die Code-Lesbarkeit und zerstückelt eine zusammenhängenden Codeblock in mehrere Einzelfunktionen.
Es gibt dafür jedoch auch eine elegante Lösung:
Snippet in VB übersetzen
using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace WindowsApplication8
{
  static class Program
  {
    [STAThread]
    static void Main()
    {
      Application.Run(new TheForm());
    }

    public class TheForm : Form
    {
      Label label1;
      Button button1;

      public TheForm()
      {
        label1 = new System.Windows.Forms.Label();
        label1.Location = new System.Drawing.Point(102, 14);
        label1.Size = new System.Drawing.Size(130, 13);

        button1 = new System.Windows.Forms.Button();
        button1.Location = new System.Drawing.Point(12, 9);
        button1.Size = new System.Drawing.Size(75, 23);
        button1.Text = "Start";
        button1.Click += new System.EventHandler(this.button1_Click);
        Controls.AddRange(new Control[] { label1, button1 });
      }

      private void button1_Click(object sender, EventArgs e)
      {
        // Nimmt sich ein Thread und ruft damit DoIt auf
        System.Threading.ThreadPool.QueueUserWorkItem(DoIt);
      }

      private void DoIt(object dummy)
      {
        int i = 1;
        bool Cancel = false;

        while (Cancel == false)
        {
          // Zu Demozwecken immer 1 Sekunde Pause
          System.Threading.Thread.Sleep(1000);

          // Dies ist sogenannter generischer Delegate,
          // innerhalb des Blocks vollen Zugriff auf die
          // UI zuläßt
          MethodInvoker LabelUpdate = delegate
          {
            // Innerhalb dieses Blocks können Controls
            // und Forms angesprochen werden, neue Fenster
            // erzeugt werden etc....
            label1.Text = i.ToString() + " Durchläufe absolviert";
          };

          Invoke(LabelUpdate);

          if (i % 5 == 0)
          {
            MethodInvoker QuestionDelegate = delegate
            {
              // Sogar Rückfragen sind möglich
              if (MessageBox.Show("Noch eine Runde ?", "Frage", MessageBoxButtons.YesNo) == DialogResult.No)
                Cancel = true;
            };
            Invoke(QuestionDelegate);
          }
          i++;
        }
      }
    }
  }
}

5 Kommentare zum Snippet

knoyxz schrieb am 19.11.2008:
Dein Snippet hat mir soeben einen leicht verständlichen Einstieg
ins Thema Threads ermöglicht!
Tausend DANK :-)

Besonders den MethodInvoker kann ich sehr gut gebrauchen.

knoxyz
derjaeckel schrieb am 04.06.2009:
Hat mir auch super geholfen... vielen Dank!!!
regalis schrieb am 26.03.2010:
Ich glaub ich muss meine Anwendung komplett umbauen...so einfach und übersichtlich sieht sie nämlich nicht aus :D
Danke sehr! Bitte noch mehr so leicht verständliche und gebräuchliche Snippets ;)
armintelker schrieb am 22.08.2010:
MethodInvoker: Macht einem das leben um einiges leichter :) danke.
NoBadCode schrieb am 16.04.2011:
Danke, das hat mir wirklich sehr geholfen, weiter so.
 

Logge dich ein, um hier zu kommentieren!