myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » GUI: Windows-Forms » Controls von Thread aktualisieren lassen (Invoke-/TreeView-Beispiel)
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

geschlossen (weitere Infos)
Zum Ende der Seite springen  

Controls von Thread aktualisieren lassen (Invoke-/TreeView-Beispiel)

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
myCSharp.de
Moderationshinweis von herbivore (02.03.2007 11:10):

Dies ist ein Thread, auf den aus der FAQ verwiesen wird. Deshalb ist er geschlossen.
 
Z-80 Z-80 ist männlich
myCSharp.de-Mitglied

Dabei seit: 25.11.2004
Beiträge: 29
Entwicklungsumgebung: Visual Studio 2005
Herkunft: Mecklenburg Vorpommern


Z-80 ist offline

Controls von Thread aktualisieren lassen (Invoke-/TreeView-Beispiel)

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

ich habe ein kleines Threadproblem. Ich lasse in einem TreeView einen Baum erstellen, was gut und gerne 30 Sekunden dauert. Deshalb habe ich dafür einen extra Thread laufen. Allerdings aktualisiert sich der TreeView nicht.
Zuerst habe ich es mit:

C#-Code:
                Thread t = new Thread(new ThreadStart(funktion));
                t.Start();

probiert aber immer wenn ich dann die TreeView aktualiseren will, gibt es eine Exception.
Nun habe ich es mit:

C#-Code:
private void AssemblyTreeBox_Load(object sender, EventArgs e)
{
   ct ctd = new ct(CreateTree);
   ctd.BeginInvoke(null, null);
}

TreeView tmpTreeview = new TreeView();

public delegate void Updatetreedelegate();
void UpdateTree()
{
   if (treeView1.InvokeRequired == false)
   {
      treeView1 = tmpTreeview;
      treeView1.Refresh();
   }
   else
   {
      Updatetreedelegate upd = new Updatetreedelegate(UpdateTree);
      this.BeginInvoke(upd);
   }
}

private void CreateTree()
{
   // ....
   //Baummanipulation
   UpdateTree();
   // ....
}

probiert. Stand so auf einer Microsoftseite; da war aber statt dem TreeView eine Progressbar.
In tempTreeView steht auch immer der richtige aktuelle Baum, nur leider wird beim sichtbaren treeView1 nichts angezeigt.
Wie bekomme ich es nun hin das sich der Baum stückchenweise aufbaut, und das auch angezeigt wird?
30.05.2005 21:35 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
herbivore
myCSharp.de-Poweruser/ Experte

avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 49.478
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin


herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Z-80,

ich habe mal meine Code von  TreeView abhängig vom Verzeichnislevel füllen so umgestellt, dass das Füllen in einem Thread passiert. Manchmal sagt ja Code mehr als 1000 Worte.

Zusätzlich benötigt, wird jetzt natürlich das Starten des Threads:

C#-Code:
Thread t = new Thread (new ThreadStart (PopulateTreeView));
t.Start();

und zwei Delegaten, die das eigentlich Hinzufügen übernehmen, denn das muss ja im GUI-Thread passieren:

C#-Code:
protected delegate void MethodTreeViewTreeNode (TreeView tv, TreeNode tn);
protected delegate void MethodTreeNodeTreeNode (TreeNode tnParent, TreeNode tn);

void AddRootNode (TreeView tv, TreeNode tn)
{
   tv.Nodes.Add (tn);
   tv.ExpandAll();
}

void AddChildNode (TreeNode tnParent, TreeNode tn)
{
   tnParent.Nodes.Add (tn);
   tnParent.TreeView.ExpandAll();
}

Dort habe ich jeweils noch ExpandAll hineingeschrieben, damit man immer gleich sieht, was passiert.

Im eigentlichen Algorithmus habe ich nur das direkte Hinzufügen der Knoten/Unterknoten durch die entsprechenden Invokes ersetzt (und außerdem das Füllen durch Thread.Sleep künstlich verzögert):

C#-Code:
protected void PopulateTreeView ()
{
   Hashtable htNode = new Hashtable ();

   using (StreamReader sr = new StreamReader ("data.txt", Encoding.Default)) {
      String strDir;
      while ((strDir = sr.ReadLine ()) != null) {
         String [] astrPart = strDir.Split ('\\');
         String strBegin = "";
         TreeNode tnParent = null;
         foreach (String strPart in astrPart) {
            if (strPart == "") {
               continue;
            }
            strBegin += "\\" + strPart;
            if (htNode.ContainsKey (strBegin)) {
               tnParent = (TreeNode)htNode [strBegin];
               continue;
            }
            htNode [strBegin] = new TreeNode (strPart);
            if (tnParent == null) {
               Invoke (new MethodTreeViewTreeNode (AddRootNode),
                       _tvDir, htNode [strBegin]);
            } else {
               Invoke (new MethodTreeNodeTreeNode (AddChildNode),
                       tnParent, htNode [strBegin]);
            }
            tnParent = (TreeNode)htNode [strBegin];
         }
         Thread.Sleep (500);
      }
   }
}

Zum Ausprobieren kannst du die data.txt aus dem anderen Thread herunterladen.

herbivore

Suchhilfe: 1000 Worte
30.05.2005 23:02 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Z-80 Z-80 ist männlich
myCSharp.de-Mitglied

Dabei seit: 25.11.2004
Beiträge: 29
Entwicklungsumgebung: Visual Studio 2005
Herkunft: Mecklenburg Vorpommern

Themenstarter Thema begonnen von Z-80

Z-80 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Danke, das hat mir sehr geholfen. Jetzt ist mir die ganze Angelegenheit auch viel klarer und logischer geworden.
31.05.2005 15:52 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Programmierhans
myCSharp.de-Poweruser/ Experte

avatar-1651.gif


Dabei seit: 05.04.2005
Beiträge: 4.221
Entwicklungsumgebung: VS2003-VS2013 / SAP WebIDE
Herkunft: Zentralschweiz


Programmierhans ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

@herbivore

Wie immer von Dir saubere Arbeit :-)

Der Vollständigkeit halber würde ich den Code aber noch ein bisserl erweitern mit if InvokeRequired.... Du weisst sicher was ich meine.... Der Code kann ja auch problemlos aus dem UI-Thread aufgerufen werden... dann wäre der Invoke nicht notwendig..... dann wäre dies hier wieder ein guter Artikel auf welchen man Threading-Newbies verweisen kann...
31.05.2005 16:04 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
herbivore
myCSharp.de-Poweruser/ Experte

avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 49.478
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin


herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Programmierhans,

danke! Ja, ich weiß, was du meinst. Ich hatte das gestern auch überlegt, aber da ja gerade das Ziel war, dass das Füllen durch einen extra Thread geschehen sollte, ist ja das InvokeRequiere überflüssig und und ich fand es sogar vom Kern der Sache ablenkend.

Dafür spricht jedoch, dass man in dem eigentlichen Füllalgorithmus um die aufwändige Invoke-Syntax herumkommt und dass man Invoke und "invokte" Methode schön verheiraten kann.

Deshalb komme ich deinem Hinweis auch gerne nach und liefere eine Version mit InvokeRequired:

Der Füllalgorithmus wird wie gesagt übersichtlicher (hier nur der entscheidende Auschnitt am Ende der inneren Schleife):

C#-Code:
htNode [strBegin] = new TreeNode (strPart);
if (tnParent == null) {
   AddRootNode (_tvDir, (TreeNode)htNode [strBegin]);
} else {
   AddChildNode (tnParent, (TreeNode)htNode [strBegin]);
}
tnParent = (TreeNode)htNode [strBegin];

Die beiden Add-Methoden kümmern sich jetzt selbst um das in diesem Szenario auf jeden Fall benötigte Invoke, in dem sie sich selbst "invoken".

C#-Code:
void AddRootNode (TreeView tv, TreeNode tn)
{
   if (tv.InvokeRequired) {
      Invoke (new MethodTreeViewTreeNode (AddRootNode),
              tv, tn);
      return;
   }
   tv.Nodes.Add (tn);
   tv.ExpandAll();
}

void AddChildNode (TreeNode tnParent, TreeNode tn)
{
   if (tnParent.TreeView.InvokeRequired) {
      Invoke (new MethodTreeNodeTreeNode (AddChildNode),
              tnParent, tn);
      return;
   }
   tnParent.Nodes.Add (tn);
   tnParent.TreeView.ExpandAll();
}

Der Aufruf des Thread und die Delegaten bleiben unverändert.

herbivore
31.05.2005 18:40 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
myCSharp.de
Moderationshinweis von herbivore (02.03.2007 11:11):

Früher stand dieser Thread direkt in der FAQ und an vielen Stellen wird direkt auf ihn verwiesen. Jetzt gibt es einen eigenständigen Beitrag  [FAQ] Controls von Thread aktualisieren lassen (Invoke-/TreeView-Beispiel) in der FAQ, der auf diesen Thread hier verweist, weshalb dieser Thread hier auch geschlossen ist.
 
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 15 Jahre.
Der letzte Beitrag ist älter als 15 Jahre.
geschlossen (weitere Infos)


© Copyright 2003-2020 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 12.08.2020 20:39