Ö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.
- 5893 megtekintés
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."
- A hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni
Ja hogy a Timer alapból a System.Threading névtérben van. Tök jó :)
Szeretem hogy nyitok egy fórumtémát, aztán rájövök magamtól a dolgokra :)
- A hozzászóláshoz be kell jelentkezni
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)
- A hozzászóláshoz be kell jelentkezni
É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.
- A hozzászóláshoz be kell jelentkezni
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++;
- A hozzászóláshoz be kell jelentkezni
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 hozzászóláshoz be kell jelentkezni
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.
- A hozzászóláshoz be kell jelentkezni