Szálak (C#, WPF)

Fórumok

Összeütöttem egy kis alkalmazást, ami adatokat tölt le kiszolgálókról adott időközönként. Annyit csináltam, hogy Visual Studio-ban indítottam egy új projektet, WPF alkalmazást, berángattam pár elemet ami kell, aztán megírtam a függvényeket. Van egy TextBox, amibe úgymond logol az app, tehát beleírja hogy honnét mit töltött le.

Megcsinálom a kérést:

request = HttpWebRequest.Create(url);
response = request.GetResponse();
sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);

Egyelőre csak bemutató jelleggel készült az alkalmazás egy ötlet prezentálására, semmi mást nem csinál, csak megszámolja a sorokat:


int sorok = 0;
while (!sr.EndOfStream)
{
  sr.ReadLine();
  sorok++;
}

Utána bele akartam írni a TextBox-ba, pl.:

textbox1.Text += "\n" + sorok

, de kiírta hogy másik szálon van a textbox1, mint ahonnan én el akarom érni. Írtam egy delegate-et, és a Dispatcher-rel hívom meg, de én ezt nem értem. Hogy került másik szálra mint ahol én voltam? Találtam ilyet, de sose használtam még szálakat (egyszer-kétszer kipróbáltam Java-ban, de az legalább szándékosan volt, ellentétben a mostani helyzettel), szóval nem értem.

Tehát leginkább az lenne a kérdésem, hogy mit csinált a WPF, vagy a .NET, vagy nem tudom mi, amitől a webes kérések másik szálon indultak? Vagy mi fut most másik szálon, és miért? És miért nem tudok csak úgy beleírni a textbox1-be? Ha csak simán próbálkozok (tehát

textbox1.Text += "hello"

), az működik.

Hozzászólások

Rosszul mondtam, abból a függvényből nem tudok beleírni egy hello-t se a szövegdobozba, de pl. ugyanennek az osztálynak a konstruktorából és egyéb metódusaiból működik a dolog. Ez a pontos hibaüzenet: "The calling thread cannot access this object because a different thread owns it."

Talán az is számíthat, hogy ez az eseménykezelő egy Timer eseményeit kezeli, tehát nem a felhasználó nyom meg valamit vagy hasonló.

timer.Elapsed += new ElapsedEventHandler(Timer_Elapsed);

Ez a Timer_Elapsed a problémás eset.

Gugli WPF-hez a DispatcherTimer-t ajánlja. Igaz, az is a Threading névtérben van, de ha jól sejtem, a WinFormsos Timer tulajdonságaival rendelkezik (azaz a vezérlő szálán hívódik meg az OnTick(), vagy legalábbis nem kell tartani az általad tapasztalt problémától)

Ha mégis hülyeséget írtam, bocsánat, még csak elméleti szinten foglalkoztam WPF-el (plusz egy egyszerűbb alkalmazás)

Én írtam hülységet, nem is azt használtam, hanem ezt, a System.Timers-ből (System.Timers.Timer).

De kipróbáltam amit írtál, azzal beakad a GUI mikor lekéri a címeket, szóval jó hogy külön szálon fut. Érdemes lenne alaposabban megismernem a szálak használatát.

Igaziból nem probléma ez a szó szoros értelmében (sőt, még jó is hogy így van), csak nem értem.

Nagyon sokat olvass meg ehhez.

Kulcsszavak (kb. sorban):

- thread
- ui thread
- background thread
- message loop / ui loop, dispatcher
- invoke, invokerequired

Ha ezeket nem tudod, _sosem_ fogsz tudni rendesen GUI-t programozni.

Sokan azt gondoljak, hogy a GUI programozas az drag'n'drop, meg rajzolgatas, pedig valojaban az egyik legnehezebb terulete az alkalmazasfejlesztesnek (fokepp ha reszponziv, nagy adatmennyisegekkel operalo UI-rol van szo).

----------------------
while (!sleep) sheep++;

Nem gondoltam hogy a GUI programozás drag'n'drop meg rajzolgatás, sőt jobban is tetszett a Java-féle konténeres-layoutmanageres megoldás (Microsoftos téren még nem jutottam el idáig, azt magamtól tanulom), de aztán rájöttem hogy 2 szövegmezőről meg 2 gombról van szó, és egyetlen dolgot fog csinálni a progi, szóval tökéletes lesz ha behúzom azt a pár elemet.

Tegnap is olvastam az általad említett dolgok után, a kulcsszavakra rátaláltam magamtól is :) A szálkezelésnél igaziból nem is az tűnik nehéznek hogy hogyan lehet megcsinálni, hanem hogy mikor, miért és hogyan érdemes.

A Timer gyakorlatilag egy időzített thread, ami adott időre elaltatja magát, majd a hozzárendelt esemény(eke)t lövi el minden feléledéskor. Így nyilván más thread-ben fog futni.
WPF-ben megszuntettek az Invoke-ot, helyette DependencyObjectek vannak, illetve a Dispatcher. Csinálhatnál egyet a formodra (mármint DependencyObjectet), ami a textboxodat frissiti.

Ezt olvassad el:
http://social.msdn.microsoft.com/forums/en-US/wpf/thread/360540eb-d756-…

--
"SzAM-7 -es, tudjátok amivel a Mirage-okat szokták lelőni" - Robi.