Diskuze: C# winform - dočasné vypnutí událostí
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Člen

Zobrazeno 20 zpráv z 20.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
btn.Enabled = false;
ProvadejHledani();
Application.DoEvents(); //tady se provedou nesplněné úlohy (např. kliknutí na neaktivní tlačítko)
//a až pak aktivuj tlačítko
btn.Enabled = true;
pokud knikneš na tlačítko co je Enabled = false tak se událost do tlačítka nedostane. Je divný jestli ano. To je chyba. Pod jakým .NET děláš ? zkusil si 4.7.2 ??? jinak mužeš zkusit dát Visible = false na nadřazenou komponentu tedy asi .. Panel ? Máš to na panelu že ? ty všechny tvoje komponenty včetně toho datagridview ?
Ahoj, dokud je tlačítko enabled = false a já na něj kliknu tak se
událost nespustí. Ale když dám tlačítko enabled = true a předtím jsem na
něj kliknul tak se událost spustí. Používám .NET 4.5.2.
Tlačítka mám na panelu ale dataGridView ne. Pokud dám panelu visible = false
viz. kod níže
panel.Visible = false;
Vyhledani();
panel.Visible = true;
Tak se tlačítka během vyhledávání ztratí a když je vyhledávání
dokončeno tak se objeví...
Ale to nechci aby tam tlačítka takto mizely a objevovaly se....
Děkuji za radu. Pokud přidám do kódu:
Application.DoEvents();
Tak to již funguje. Chtěl jsem se zeptat proč se událost na tlačítku spustí, když na něj bylo kliknuto během jeho neaktivního stavu? Tlačítko si tedy musí pamatovat, že během enable = false bylo stisknuto?
když klikneš na tlačítko, které už je Enabled = false tak se událost
nevyvolá
pokud ano je něco špatně a máš špatně časování. ono totiž chvíli
trvá než se Enabled = false provede... víš ... jinak je dobré si to
ošetřit v metodě buttonXX_Click jestli si tam už jedno byl nebo ne nějakou
globální proměnnou ..
aby sma oba mlivili o tom samém .. když je tlačítko Enabled = false a ty na něj klikneš a pak třeba za 1 sec dáš Enabled = true tak se to kliknutí starý 1 sec nikde nepamatuje .. pokud se událost vyvolá máš něco špatně ...děláš něco špatně .. jestli si Event od tlačítka zadáváš sám formou ... += NEW .. tak to tam možná dáváš dvakrát .. protože přidávání eventů se pamatuje .. možná by sis měl zobrazit okno konzole a příkazem Console.WriteLine si vypisovat nějaký pomocný údaje ...
Dovolím si podat své vysvětlení:
Proč to "funguje", už napsal zelvicek. Taky napsal
správně, že DoEvents je lepší se vyhnout (respektive musíš si být
jistý, že můžeš bez obav použít), protože ti může spustit metodu,
kterou nečekáš.
Pokud DoEvents dává do kódu začátečník, je dost pravděpodobné, že
nemá dobrou koncepci aplikace. Doporučuji navrhnout aplikaci tak, aby nevadilo
kliknout na zmíněné tlačítko a button vypnout jen pro oko uživatele.
Příspěvky jerryM doporučuji v tomto vlákně ignorovat (jsou nepřesné a
matoucí).
zelvicek: podle nadpisu jde o WF
čau tak já sem teda ten
matoucí příspěvek ..
klidně používej DoEvents() ... čert ví proč ti to tlačítko dělá
...
každopádně datagridview z WinFomrs vyžaduje vypnutí všech událostí tim
... -= new ....
obzvlášť když hledáš v gridu dlouho ... jde o to, že celý WinForms jsou
jednovláknový ...
ono by to asi jinak s tou technologií nešlo ... bohužel z toho vyplývá
mnoho jiných problémů
radši časem přejdi na WPF
Díky za info a pomoc.
Mám dotaz ohledně "Doporučuji navrhnout aplikaci tak, aby nevadilo kliknout
na zmíněné tlačítko a button vypnout jen pro oko uživatele."
Myslíš to tak že bych si měl nastavotat někde flag (globální proměnnou). Pokud budu vyhledávat v datagridview tak ji nastavit na true a pak do každé události, kterou nechci během vyhledávání spustit přidat if:
if (flag = true)
return;
Tím bych zamezil spouštění událostí během vyhledávání...
Takhle jsi to myslel? Nebo jak psal zelvicek pouzit vlakna? Vlákna jsem moc
nepoužíval, tak si nejsem jistej jestli bych to zvládl.
Díky
Zvládnutí vláken je více-méně nutnost. Ale ničeho se neděs, raketová věda to není.
Mkrni na https://www.codeproject.com/…or-Beginners. Článek je to dlouhý, ale popisuje problematiku celkem srozumitelně. Pokud by ses chtěl hned vrhnou na vyzkoušení, podívej se na kód na konci článku.
Věřím, že s tím problém mít nebudeš, BackgroundWorker je na inetu dobře popsaný EN i CZ.
P.S. kaju se, technologie skutečně zmíněná je.
Ano třeba i tak nějak. Záleží na řešení aplikace.
Obecně můžu poradit jen:
Vlákna samozřejmě jsou dobrá věc, ale u i vláken musíš pamatovat na to,
že se jednotlivá vlákna dokončí v různých časech...
Určitě je dobré myslet i na to, že uživatelé aplikací jsou schopni všeho
U složitějších aplikací
ošetřit vše, a neošetřovat to, co už ošetřené je, zabere fůru času
(zvláště když se to řeší dodatečně). Proto musíš od začátku
navrhovat aplikaci tak, aby ses neztrácel v logice aplikace, jejím kódu a aby
nedocházelo ke konfliktům.
Takže studuj články a trénuj. Časem se to naučíš, hned nejde skoro nic.
Chybami se naučíš nejvíc.
Dnes jsem se díval na včerejší příspěvek, a doplním ještě nějaký příklad:
Řekněme, že na formuláři spustím nějaké složitější filtrování
(F) v jiném vlákně, které bude výsledek zobrazovat v nějakém listu (X).
Pak tam bude tlačítko (T) "Vymaž list X".
Pokud stisknu tlačítko T za běhu F, tlačítko T přeruší vlákno F a
vymaže list X.
A s tím tlačítkem v jednovláknové aplikaci je to podobné. Jen s tím
rozdílem, že se na tlačítko za běhu F kliknout nedá. A pokud na něj
klikneš tak se ten klik projeví, až poté co se F dokončí a je jedno jestli
tlačítko bylo aktivní nebo ne.
V případech kdy je třeba dodržovat nějaký postup (pořadí) práce je
dobré nějakým způsobem indexovat fáze postupu.
Ahoj, omlouvám se za tak pozdní reakci. Nějak jsem nestíhal.
Takže myslíš, že použítí vláken (BackgroundWorker) můj problém
nevyřeší?
Nejsnadnější postup teda bude blokování spuštěné události globální
proměnnou, kterou během vyhledávání nastavím na true a pak do každé
události podmínku:
if (flag == true)
return;
Jinak děkuji za vysvětlení problému....
Právě, že vyřeší. Druhé vlákno zajistí to, že budeš moct pracovat formulářem, proto ti bude fungovat i vyřazení tlačítek (protože zprávy okna budou fungovat hned). Takže musíš vyřadit vše (nebo nějak ošetřit), co nechceš aby uživatel spustil v průběhu hledání (je jedno jestli proměnnou, nebo vyřazením (Enabled=false)). Jen to musíš udělat před spuštěním vlákna a po jeho dokončení, protože z vlákna nelze přistupovat k formu.
Ahoj,
vytvořil jsem si backGroundWorker kde dělám filtraci. Mohu ve vlákně
(metodě) backgroundWorkerFiltraceDat_DoWork přistupovat k dataGridView?
Protože když ve vlákně použiji viewKatalogBindingSource.Filter =
filtrId; tak mi vyskočí chybové okno (obr v příloze).
A filtr se neprovede. V dataGridView mám všechny řádky (celou databázi) jen
na prvních řádcích jsou filtrovaná data... Ale už dobře funguje blokace
tlačítka během filtrace...
Pokud dám viewKatalogBindingSource.Filter = filtrId; do metody
backgroundWorkerFiltraceDat_RunWorkerCompleted tedy mimo vlákno. Tak
filtrace v dataGridView funguje ale blokace tlačítka ne....
Díky za pomoc
BackgroundWorker pracuje v jiném vlákně, než je hlavní UI. Pro
komunikaci s uživatelem z vlákna BW, např. pro zobrazení průběhu
(progressbar) se používají metody BW, např. ProgressChanged...
Mrkni se na toto video
https://channel9.msdn.com/…plikacich-CZ
je to tam krásně vysvětleno...
Tak ještě jednou:
Udělal jsi chybu v tom, že a) jsi na UI vlákno "pověsil" ne-UI
funkcionalitu; b) hledáš v gridu (UI prvek) namísto v datech. Takže to
předělej na Task nebo BackgroundWorker.
DataGridView je vizuální prvek a operace, které má vykonat, vykonává v
UI vlákně. Po dobu vykonávání úkolů UI vlákno nevykonává úkoly jiné.
A pokud mu dáš mnoho dat, operace zabírají mnoho času.
IMHO je tedy lepší data uložit do paměti, a operace (hledání,
filtrování, ...) vykonávat nad daty v paměti (kde má přístup i
BackgroundWorker a jeho vlákno) než to nechat na DGW a UI vlákně.
P.S. neumí data hledat a filtrovat zdroj dat (třeba nějaký DB engine) ?
Zobrazeno 20 zpráv z 20.