[C# / SQL] Threading, Treeview vullen vanuit een Thread

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • skaars
  • Registratie: Oktober 2004
  • Laatst online: 07-02 11:29
Voor jullie ervaren programmeurs zal het allemaal wel heel bekent klinken.

Het betreft hier trouwens VS2008
Ik ben bezig met een projectje waarbij na het starten van de applicatie een SQL query wordt uitgevoerd. Deze is nodig voor het vullen van een treeview met database informatie. Nou is mijn probleem dat tijdens dit proces de applicatie niet meer aanspreekbaar is voor wat dan ook. Deze wacht namelijk op die informatie... en simpele muisklik in het form resulteert dan ook meteen in een "Reageert niet" titel in de titelbalk.

Nou dacht ik dit op te kunnen lossen via Threading, zoals ik al een keer eerder heb gedaan met VS2003. Daar kon je volgens mij een method in een thread plaatsen en er was niets aan de hand. Dat moet nu iets anders in VS2008 maar ik kom er niet uit. Je kan niet vanuit een thread een treeview vullen.

Het kan ook zijn dat ik het gehele threading verhaal moet vergeten, als dat zo is hoor ik dat graag. En als je code wilt zien geldt dat ook.

Alvast bedankt

het internet is als een neus, je moet eruit halen wat erin zit


Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 19-09 10:19
skaars schreef op vrijdag 29 mei 2009 @ 11:42:
Voor jullie ervaren programmeurs zal het allemaal wel heel bekent klinken.

Het betreft hier trouwens VS2008
Ik ben bezig met een projectje waarbij na het starten van de applicatie een SQL query wordt uitgevoerd. Deze is nodig voor het vullen van een treeview met database informatie. Nou is mijn probleem dat tijdens dit proces de applicatie niet meer aanspreekbaar is voor wat dan ook. Deze wacht namelijk op die informatie... en simpele muisklik in het form resulteert dan ook meteen in een "Reageert niet" titel in de titelbalk.

Nou dacht ik dit op te kunnen lossen via Threading, zoals ik al een keer eerder heb gedaan met VS2003. Daar kon je volgens mij een method in een thread plaatsen en er was niets aan de hand. Dat moet nu iets anders in VS2008 maar ik kom er niet uit. Je kan niet vanuit een thread een treeview vullen.

Het kan ook zijn dat ik het gehele threading verhaal moet vergeten, als dat zo is hoor ik dat graag. En als je code wilt zien geldt dat ook.

Alvast bedankt
Je kunt het beste even zoeken naar "Backgroundworker" die kan precies dit voor je doen :)

http://dotnetperls.com/Co...dWorker-Introduction.aspx

(Is ook een thread, maar met een structuur er omheen om precies dit op te lossen).

[ Voor 6% gewijzigd door roy-t op 29-05-2009 12:06 ]

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 00:16

Matis

Rubber Rocket

Yup, kan die alleen maar beamen. Een backgroundworker is een eenvoudige manier om een thread te starten en het *percentage* terug te vragen van de voortgang van je worker.

Je kan aan die getallen natuurlijk ook hele andere waardes hangen; 1 is bijvoorbeeld inlezen query, 2 is schrijven van gegevens, 3 is een fout enz. enz.

If money talks then I'm a mime
If time is money then I'm out of time


Acties:
  • 0 Henk 'm!

  • sig69
  • Registratie: Mei 2002
  • Laatst online: 10:17
Je zou ook het eventueel ook nog kunnen oplossen door het hele proces asynchroon te programmeren, bij voor door SqlCommand.BeginExecuteReader en dergelijke te gebruiken.

Roomba E5 te koop


Acties:
  • 0 Henk 'm!

  • Eguna
  • Registratie: Januari 2002
  • Laatst online: 01-09 18:00

Eguna

AMD is liev

kom op joost, jaren op school en nog steeds zo lopen te rommelen met code :p
je kan dit wel oplossen door in runtime een nieuwe treeview te bouwen, die te vullen en als hij klaar is in het form te stoppen maar volgens mij ga je helemaal de verkeerde kant op met je ontwerp.
Een treeview vult van nature enorm snel, dus ik vraag me af wat je er precies probeert in te stoppen.
Als het om honderdduizenden records gaat, moet je je even af vragen of het wel nodig is?
Misschien is de 'gebruiker' al blij met de eerste 100, en naar wens de volgende 100. Paging en resultaatbeperking is een veel nettere manier om dit soort problemen op te lossen.

gr jaap

My life for hire!


Acties:
  • 0 Henk 'm!

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

Een andere veel gebruikte techniek is lazy loading. Je haalt dan alleen de nodes op welke je nodig hebt (dus bij expand van een treeviewitem). Je hebt dan (vrijwel altijd) sneller resultaten omdat de resultaten beperkter zijn.

If it isn't broken, fix it until it is..


Acties:
  • 0 Henk 'm!

  • Xiphalon
  • Registratie: Juni 2001
  • Laatst online: 15:18
Je kan prima in een andere thread een treeview (of bijna elk control) vullen. Maak dan in je thread gebruik van BeginInvoke.

Acties:
  • 0 Henk 'm!

  • pasz
  • Registratie: Februari 2000
  • Laatst online: 01-09 23:08
Dit ruikt naar heel veel queries ipv 1 snelle. Een boompje opbouwen mag dit soort gedrag nooit veroorzaken.

Hoe ziet je tabel eruit ?
Heb je de SQL profiler wel eens gebruikt om te kijken wat er allemaal gebeurd ?

woei!


Acties:
  • 0 Henk 'm!

  • cariolive23
  • Registratie: Januari 2007
  • Laatst online: 18-10-2024
een SQL query
Welke query is dat en waarom is deze zo gruwelijk langzaam dat het opvalt? Ga met EXPLAIN in de database achterhalen wat het echte probleem is met de performance, daar heb je (in eerste instantie) meer aan dan iets aanpassen in de presentatie van jouw applicatie.

Acties:
  • 0 Henk 'm!

  • skaars
  • Registratie: Oktober 2004
  • Laatst online: 07-02 11:29
cariolive23 schreef op vrijdag 29 mei 2009 @ 12:53:
[...]
Welke query is dat en waarom is deze zo gruwelijk langzaam dat het opvalt? Ga met EXPLAIN in de database achterhalen wat het echte probleem is met de performance, daar heb je (in eerste instantie) meer aan dan iets aanpassen in de presentatie van jouw applicatie.
Het is niet bepaald een query. Mijn fout. Het is een functie uit .NET 2.0, sqldatasourceEnumerator. Die zoekt naar bestaande SQL servers op het lokale netwerk. En omdat dat volgens mij een soort ping actie is moet je daar even op wachten. en de applicatie dus ook.

Maar ik ga wel even kijken of ik met jullie informatie verder kom.

[ Voor 5% gewijzigd door skaars op 29-05-2009 13:49 ]

het internet is als een neus, je moet eruit halen wat erin zit


Acties:
  • 0 Henk 'm!

  • Eguna
  • Registratie: Januari 2002
  • Laatst online: 01-09 18:00

Eguna

AMD is liev

dan is het nog makkelijker op te lossen, sleep een backgroundworker op je form, doe in de do_work event een stuk code die de lijst (in het geheugen, niet in de treeview zelf) gaat maken, zet ondertussen boven je treeview een label 'bezig met ophalen data', en doe in de _runworkercompleted event waarin je de treeview vult met je verzamelde data. Wel natuurlijk Backgroundworker1.runworkerasync(); aanroepen in form load ;)

[ Voor 11% gewijzigd door Eguna op 29-05-2009 13:58 ]

My life for hire!


Acties:
  • 0 Henk 'm!

  • jos707
  • Registratie: December 2000
  • Laatst online: 19-09 14:23
Eguna schreef op vrijdag 29 mei 2009 @ 13:57:
dan is het nog makkelijker op te lossen, sleep een backgroundworker op je form, doe in de do_work event een stuk code die de lijst (in het geheugen, niet in de treeview zelf) gaat maken, zet ondertussen boven je treeview een label 'bezig met ophalen data', en doe in de _runworkercompleted event waarin je de treeview vult met je verzamelde data. Wel natuurlijk Backgroundworker1.runworkerasync(); aanroepen in form load ;)
Heel waarschijnlijk ga je een mooie cross thread exception krijgen als je je treeview probeert up te daten vanuit je backgroundworker thread. Om dit op te lossen zal je aan de slag moeten gaan met een delegate die ervoor zal zorgen dat je treeview wordt geupdate vanuit de GUI thread.

Acties:
  • 0 Henk 'm!

  • Eguna
  • Registratie: Januari 2002
  • Laatst online: 01-09 18:00

Eguna

AMD is liev

Maar ik zeg ook niet dat het zo moet, ik bedoel dat je bovenaan in je form een nieuwe array of iets dergelijks maakt, die laat vullen in met runworkerasync, en de completed event de waardes uit de arraylist in de treeview laten stoppen. Op die manier heb je geen lag meer, want het vullen van een treeview met een paar waardes is peanuts voor .NET.

My life for hire!


Acties:
  • 0 Henk 'm!

  • m33p
  • Registratie: September 2002
  • Laatst online: 05-09 15:26
jos707 schreef op vrijdag 29 mei 2009 @ 23:39:
[...]

Heel waarschijnlijk ga je een mooie cross thread exception krijgen als je je treeview probeert up te daten vanuit je backgroundworker thread. Om dit op te lossen zal je aan de slag moeten gaan met een delegate die ervoor zal zorgen dat je treeview wordt geupdate vanuit de GUI thread.
Dat is het mooie van de BackgroundWorker, de ProgressChanged en RunWorkerCompleted events worden uitgevoerd in de main thread, terwijl DoWork vanuit de andere thread updates doorgeeft aan ProgressChanged.

Acties:
  • 0 Henk 'm!

  • skaars
  • Registratie: Oktober 2004
  • Laatst online: 07-02 11:29
....mooie cross thread exception krijgen...
Die kreeg ik dus ook.

Maar ik krijg nog niet de informatie die gewonnen is op de "achtergrond", naar de "voorgrond", dus in de Treeview.

het internet is als een neus, je moet eruit halen wat erin zit


Acties:
  • 0 Henk 'm!

  • creator1988
  • Registratie: Januari 2007
  • Laatst online: 20:56
Updaten vanaf thread 1 naar main thread is vrij eenvoudig. Idee is om een MethodInvoker aan te maken, die een delegate (functie als variabele heeft). Deze kan je met een functie asynchroon laten draaien.

Door this.Invoke aan te roepen vanaf de methode die je in je MethodInvoker hebt aangeroepen, en ook daar weer een delegate mee te geven kan je dingen op je main thread updaten.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
        private void Form1_Load(object sender, EventArgs e)
        {
            //MethodInvoker zorgt ervoor dat we iets async kunnen draaien
            new MethodInvoker(()=>DoWork()).BeginInvoke((asyncResult) => { /* actie om uit te voeren als je klaar bent */ }, null);
        }

        //gaat op een aparte thread draaien
        private void DoWork()
        {
            //long lasting operation
            System.Threading.Thread.Sleep(3000);
            //updaten van iets op de main thread
            this.Invoke(new MethodInvoker(() => label1.Text = "bezig bijna klaar"));
            System.Threading.Thread.Sleep(5000);
            this.Invoke(new MethodInvoker(() => label1.Text = "klaar"));
        }

Acties:
  • 0 Henk 'm!

  • skaars
  • Registratie: Oktober 2004
  • Laatst online: 07-02 11:29
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
        private void Form1_Load(object sender, EventArgs e)
        {
            //MethodInvoker zorgt ervoor dat we iets async kunnen draaien
            new MethodInvoker(()=>DoWork()).BeginInvoke((asyncResult) => { /* actie om uit te voeren als je klaar bent */ }, null);
        }

        //gaat op een aparte thread draaien
        private void DoWork()
        {
            //long lasting operation
            System.Threading.Thread.Sleep(3000);
            //updaten van iets op de main thread
            this.Invoke(new MethodInvoker(() => label1.Text = "bezig bijna klaar"));
            System.Threading.Thread.Sleep(5000);
            this.Invoke(new MethodInvoker(() => label1.Text = "klaar"));
        }
Dit is precies wat ik zocht, alleen jammer dat het iets boven m`n pet gaat.

asyncResult Kreeg ik niet te pakken en heb nu AsyncCallback, het werkt, maar of dit de bedoeling is...

En klopt het dat als ik dan weer in m`n main thread iets wilt doen met die treeview, bijvoorbeeld een treeview1.Sort(), moet ik dan weer een this.Invoke(new method... etc schrijven in deze regel bij het stukje "actie om uit te voeren als je klaar bent"

new MethodInvoker(()=>DoWork()).BeginInvoke((asyncResult) => { /* actie om uit te voeren als je klaar bent */ }, null);

Bedankt voor de hulp :D

het internet is als een neus, je moet eruit halen wat erin zit


Acties:
  • 0 Henk 'm!

  • creator1988
  • Registratie: Januari 2007
  • Laatst online: 20:56
Nee, je actie die wordt gedraaid als ie klaar is, wordt op je main thread gedaan. Hier kan je dan ook sorten.
Pagina: 1