C# WPF szálkezelés

C# WPF szálkezelés
2013-10-08T10:56:44+02:00
2013-10-09T17:36:21+02:00
2022-11-29T20:25:39+01:00
Peti_22
Üdv,

Egy olyan alkalmazást készítek amiben egy szinte végtelen ciklus fút. Statisztikák fertilitásához futtatok összehasonlításokat egy hátul tesztelős while ciklusban. Az a gondom, hogy amíg a ciklus fút ami órákig tart addig nem tudom mozgatni az ablakot, teljesen lefagy. Szálkezeléssel szeretném megoldani a dolgot, de ezen a téren nincsenek ismereteim ezért kérnék egy kis segítséget.

Az eseményeket egy gomb lenyomása indítja el ahol egy metódusban történik a ciklus futtatása. Közben a képernyőre egy TextBlock-ba kiírja a számokat.
Mutasd a teljes hozzászólást!
Helló!

Mindenképp valamilyen párhuzamosítást használj. Application.DoEvents nem szép megoldás, egyfajta workaroundnak tartom.
A Thread túl nyers dolog, kellemetlen a szinkronizálása.
Fontold meg Task-ok használatát (async, await), de ahogy kiveszem, a te problémádra a legmegfelelőbb megoldás a BackgroundWorker, a ReportProgressben pedig infókat is küldhetsz az UI-nak.
Javaslom a Cancellation-t is tedd lehetővé, mert idegesítő, mikor nyomkodod a Cancel gombot és nem áll le a művelet...

Mutasd a teljes hozzászólást!

  • using System.Threading; static void Main( string[] args ) { Thread t = new Thread( NewThread ); t.Start(); } static void NewThread() { while(..) { } } vagy using System.Threading; new Thread(() => { Thread.CurrentThread.IsBackground = true; /* itt fut a kódod */ Console.WriteLine("Hello, world"); while(..) { } }).Start();
    Mutasd a teljes hozzászólást!
  • PTiszai példája jó, csak onnan körülményesebb egy WPF ablakba adatokat küldeni.

    A BackgroundWorker osztály RunWorkerAsync metódusával viszont elég egyszerűen el tudod érni, amit leírtál.
    Mutasd a teljes hozzászólást!
  • Mutasd a teljes hozzászólást!
  • Talán nem kell szálkezelés, elég ha időnként átadod a vezérlést a ciklusból:
    Nézd meg a súgóban :

    Application.DoEvents();
    Mutasd a teljes hozzászólást!
  • Helló!

    Mindenképp valamilyen párhuzamosítást használj. Application.DoEvents nem szép megoldás, egyfajta workaroundnak tartom.
    A Thread túl nyers dolog, kellemetlen a szinkronizálása.
    Fontold meg Task-ok használatát (async, await), de ahogy kiveszem, a te problémádra a legmegfelelőbb megoldás a BackgroundWorker, a ReportProgressben pedig infókat is küldhetsz az UI-nak.
    Javaslom a Cancellation-t is tedd lehetővé, mert idegesítő, mikor nyomkodod a Cancel gombot és nem áll le a művelet...

    Mutasd a teljes hozzászólást!
  • A folyamatát már szépen elvégzi akadás nélkül a háttérben, de az UI-nak nem tudok infót küldeni. Szeretném látni minden egyes lefutás után az új adatokat kiírva a TextBlock-ban, de ezt nem tudom elérni.

    U.I.: Áhhh megvan! Köszönöm! Több hozzáoszlásból jutottam el a megoldásig, de akié igazán segített az: Madamm
    Mutasd a teljes hozzászólást!


  • amikor ordít, hogy valaki winform-ról jön...
    szeretném én azt a pillanatot látni, amikor app.doevents-et használ

    a legmegfelelőbb megoldás az lenne, ha a bindinget megtanulja
    akkor ez a bgworker reportprogress rögtön felejtődik.
    Mutasd a teljes hozzászólást!
  • Nem akarok személyeskedni, de hidd el, egy hozzászólásból nem tudod megállapítani, hogy ki honnan jön. Most sem találtad el. Két éve WPF-elek, Winformsal nem nagyon dolgoztam.

    Idéznék MSDN-ről:
    Calling this method causes the current thread to be suspended while all waiting window messages are processed. If a message causes an event to be triggered, then other areas of your application code may execute. This can cause your application to exhibit unexpected behaviors that are difficult to debug. If you perform operations or computations that take a long time, it is often preferable to perform those operations on a new thread. For more information about asynchronous programming, see Asynchronous Programming Model (APM).


    Forrás: Application.DoEvents Method MSDN

    Emellett ha alkalmazol valamilyen párhuzamosítást, valószínűleg gyorsabban is fog lefutni az adott feladat, és az UI szálat se fogja.

    Még egy érv a BW mellett, hogy szinkronizálva van az UI tread-hez, tehát nem kell explicit módon szinkronizálnod.

    Task hátránya pedig, hogy bonyolultabb a "reportProgress" folyamat.

    Még egy forrás, amiből kiderül, hogy a WPF és a BW nem ütik egymást:
    ElegantCode

    A Binding tényleg nagyon hasznos dolog. Ez valóban más szemléletet igényel. Az viszont megint kérdés, hogy hogyan bindingelsz valamit külön szálból. Csináltál már ilyet? Én még nem, és úgy látom nem is olyan egyszerű (Klikk)

    Bocsi, hosszú lett.
    Mutasd a teljes hozzászólást!
  • egy ideje wpf-ezek, szóval képben vagyok néhány fogalommal.
    továbbra is kérdem, hogy csinálsz app.doevents-t wpf alatt

    attól, hogy belinkelsz ide egy oldalt, nem fogok bw-t használni
    ugyan lehet, sőt lehet a reportprogrssből egyensen updatelni az ui-t, de - és bocsáss meg - ezt hívják gányolásnak.

    és igen, lehet külön task/theadból bindingeli
    fura, hogy 2 év wpf után idáig még nem jutottál el....
    Mutasd a teljes hozzászólást!
  • továbbra is kérdem, hogy csinálsz app.doevents-t wpf alatt

    Nem értem, ez most kérdés? Ott van az msdn-es linkembe. Nem egy bonyolult dolog meghívni egy metódust egy loopban :)

    ugyan lehet, sőt lehet a reportprogrssből egyensen updatelni az ui-t, de - és bocsáss meg - ezt hívják gányolásnak.

    Erre találták ki :) Winformson nyersen updatelheted az ui-t - ott ez rendben is van, WPF-ben én előbb updatelném a VM-et, ami meg össze van kötve a felülettel. Te hogy csinálnád?

    és igen, lehet külön task/theadból bindingeli
    fura, hogy 2 év wpf után idáig még nem jutottál el....

    Ez egy szakmai fórum. Te hogy csinálod? Kíváncsi vagyok, oszd meg velünk. Szerinted hogyan oldható ez meg szépen? Én most hírtelen nem tudok rá szép megoldást.
    Mutasd a teljes hozzászólást!
  • Nem értem, ez most kérdés? Ott van az msdn-es linkembe. Nem egy bonyolult dolog meghívni egy metódust egy loopban :)

    Az a része is megvan, hogy azt winformhoz találták ki?

    elöbb ezt írtad
    a BackgroundWorker, a ReportProgressben pedig infókat is küldhetsz az UI-nak.

    most meg ezt
    Erre találták ki :) Winformson nyersen updatelheted az ui-t - ott ez rendben is van, WPF-ben én előbb updatelném a VM-et, ami meg össze van kötve a felülettel.

    most az UI-t vagy a VM-et updateled, mert nem mindegy

    Ez egy szakmai fórum. Te hogy csinálod? Kíváncsi vagyok, oszd meg velünk. Szerinted hogyan oldható ez meg szépen? Én most hírtelen nem tudok rá szép megoldást.

    link
    Mutasd a teljes hozzászólást!
  • Érdekel a téma, megtekintettem a szakmai véleményeket az Application.DoEvents-ről.

    1. MSDN-en figyelmeztetnek a veszélyekre
    2. Itt részletes magyarázatot kapunk - példákkal, hogy milyen hibát okozhat. (Pl, ha a felhasználó duplán kattint a gombra, ami a loopot elindítja, akkor az először futó loop futása felfüggesztrésre kerül, lefut a másodki loop, aztán folytatódik az első loop, ami minimum összekever mindent, ha nem vezet exception-hoz.) Ez engem már elrettentett a használatától :)
    3. Ugyanitt egy rövid vélemény:
    Can be, but it's a hack.
    Azaz - használható, de ez egy hack. Én nem fogalmaztam ilyen szélsőségesen.

    Itt egy vélemény, ami a Task felé billenti a mérleg nyelvét.

    Mérlegelni kell azt is, hogy a DoEvents nem egy párhuzamosító eszköz. Annyit tesz, hogy végrehajtja a várakozó feladatokat, ami az UI-ra vár. BW ezzel szemben a hosszú feladatokat megoldja egy másik szálban, és szól ha végzett / haladt a feladatával. Tehát nagy valószínűséggel gyorsabban fog lefutni ugyan az a feladat.






    Mutasd a teljes hozzászólást!
  • Az a része is megvan, hogy azt winformhoz találták ki?

    Nekem megvan! Neked is?

    infókat is küldhetsz az UI-nak

    Ez elég absztrakt dolog. Ez alatt én nem azt értem, hogy
    pbProgress.Value = x;
    Hanem, hogy adatokat küldesz az UI-nak. Senki nem beszélt direkt írásról, ahogy VM-ről sem egészen addig, míg rám nem sütötted, hogy az UI direktben írása gányolás.

    t1 - nem külön szál, és direktben írod az UI-t, köze nincs a Bindinghez.
    t2 - Dispatcher-en keresztül direktben írod az UI-t. Megint köze sincs bindinghez.

    A kérdésem továbbra is fennáll;
    és igen, lehet külön task/theadból bindingeli

    Hogyan csinálod elegánsan?
    Mutasd a teljes hozzászólást!
  • az adott linken egy kicsit scrollozz már lefelé
    Mutasd a teljes hozzászólást!
  • Mutasd a teljes hozzászólást!


  • A DoEvents a winform-hoz lett kitalálva
    Wpf alatt sokkal szebb megoldások léteznek.

    alapvetően meg kell ismerkedni az adatkötési lehetőségekkel.
    Továbbá képben kell lenni a Dispatcher működésével.

    véleményem szerint:
    ami a program mellett fut és hosszabb távon (akár a program egész élete alatt) az thread vagy task a feladattól függően.

    ami csak egy feladatot hajt végre párhuzamosan az task.

    Ez a backgroundworker a Reportprogress-el pont annyira idejétmúlt mint a doevents.
    Teljesen felesleges, hiszen az egész update a szálon belül bármikor megtehető
    Ez alól mondjuk kivétel a dependencyProperty - mert ott kénytelen vagy diszpacsolni - de mire odáig eljut a tanulásban a topicnyitó, addigra már ezt is érteni fogja, hogy miért
    Mutasd a teljes hozzászólást!


  • "most az UI-t vagy a VM-et updateled, mert nem mindegy"


    Hát ha MVVM-ben gondolkodunk, akkor nagyon nem

    Az a "menő", ha egy VM-et (vagyis egyszerűen egy osztálypéldányt) módosítasz.
    Erre elég kifinomult eszközök vannak többszálú környezetben is
    Innen meg nemnagyon érdekel, hogy mikor jó a GUI szállnak ezt megjeleníteni, de főként semmiként nem akarom fenntartani a kis lockolásaimmal a megjelenítést.

    Csak prezentálom, hogy mit kell megjelenítenie (VM-be írom), onnan meg csinálja, ahogy tanulta.

    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd