Cross-thread operation not valid – .NET – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Cross-thread operation not valid – .NET – Fórum – Programujte.comCross-thread operation not valid – .NET – Fórum – Programujte.com

 

Kubas1290
Stálý člen
2. 8. 2021   #1
-
0
-

Ahoj,

při svém programování jsem narazil na další chybu se, kterou si nevím rady :(

Ve vedlejším vláknu mám spuštěný cyklus, ve kterém vždy po nějaké době se ptám serveru, jestli vedoucí spustil hru (tím, že přes JSON aktualizuju třídu, ve které mám bool IsGameOn) a pokud ano, tak poté se daná hra spustí všem ostatním hráčům, kteří jsou v dané lobby.

Problém, ale je že poté se hlavním tokem programu stane právě toto vlákno, u kterého potřebuji, aby mohlo přistupovat k ostatním prvkům v programu (jako jsou například Labely, Buttony atd..) a právě pokud toto vlákno se pokusí změnit nějakou hodnotu těmto prvkům, tak program hodí chybu typu: Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on.

Díval jsem se, že se to řeší přes nějakého BackgroundWorker, ale moc jsem nepochopil jak to funguje.

Nejlepší by pro mě bylo, kdyby se z tohoto vedlejšího vlákna, se vyvolala nějaká událost (vzávisloti na té proměnné IsOnGame), která by běh programu opět vrátila do hlavního vlákna, akorát moc nevím jak na to :(

Nepomohl by mi s tím prosím někdo? 

Moc díky :-)

Nahlásit jako SPAM
IP: 62.141.28.–
Kubas1290
Stálý člen
2. 8. 2021   #2
-
0
-

#1 Kubas129
Nebo je možný v hlavním vláknu počkat na dokončení vedlejšího vlákna? Přes nějaký příkaz

Nahlásit jako SPAM
IP: 62.141.28.–
Kubas1290
Stálý člen
2. 8. 2021   #3
-
0
-

Jaký je rozdíl mezi třídou Task a třídou Thread ? Cháou správně, že obě tyto třídy spustí nové vlákno?

Proč pouze třída Task má metodu WaitAll()? Má třída Thread obdobnou metodu? 

Nahlásit jako SPAM
IP: 62.141.28.–
Kit+15
Guru
2. 8. 2021   #4
-
0
-

#1 Kubas129
Vyzkoušej semafory, jsou na to určeny.

Nahlásit jako SPAM
IP: 85.160.41.–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
Kubas1290
Stálý člen
2. 8. 2021   #5
-
0
-

Zjistil jsem, že se vlastně bez toho pomocného vlákna můžu obejít, ale stejně by mě zajímalo jaký je rozdíl mezi Task a Thread. Co jsem vyčetl, tak snad třída Task by měla sama od sebe spolupracovat a využívat třídu Thread a fond vláken ThreadPool. Ale proč teda by programovací prostředí nabízelo uživateli i samotnou třídu Thread?

Nahlásit jako SPAM
IP: 62.141.28.–
Kit+15
Guru
2. 8. 2021   #6
-
0
-

#5 Kubas129
Task je proces, Thread je vlákno jednoho procesu.

Nahlásit jako SPAM
IP: 85.160.41.–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
Mutagen
~ Anonymní uživatel
549 příspěvků
3. 8. 2021   #7
-
0
-

Já když pracuju s vlákny tak si většinou vytvářím eventy co mi posilaj data z vlákna ven a pokud potřebuju rpacovat s GUIčkem, tak použiju delegat a invoke

Nahlásit jako SPAM
IP: 185.138.71.–
3. 8. 2021   #8
-
0
-

Task není proces, task doslova přeloženo je úloha. Task se provádí v samostatném vlákně. Používají se vlákna z Thread Pool, což je skladiště spících vláken. Task tedy vlákno nevytváří a po skončení práce vlákno odloží zpět do Thread Pool, takže nezaniká. BackGroundWorker vlákno vytváří a po skončení práce vlákno zaniká - stojí to systémové prostředky. Používat Task je jednoduché. Doporučuji "Paralelní programování a vícevláknové aplikace v C# .NET" na https://www.itnetwork.cz/csharp  Přístup k celému seriálu tě bude stát pár stovek, ale opravdu se z něj něco naučíš.

GUI má svoje vlákno, jakákoliv manipulace s prvky GUI z jiného vlákna vyžaduje synchronizaci. U BackGrounWorkeru na to byly synchronizované metody, hledej v dokumentaci, jsou tam i ukázky jak na to. Jak synchronizovat Task najdeš v tom seriálu.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Kubas1290
Stálý člen
3. 8. 2021   #9
-
0
-

Fajn zjistil jsem, že bez toho pomocného vlákna se přeci jen neobejdu, problém mám ovšem v tom, že poté celá aplikace již nadále běží v tomto novém vláknu, je nějaký způsob, kterým bych se opět vrátil do původního vlákna? Tak abych nadále mohl používat komponenty z prvního vlákna atd..

pozn. zkoušel jsem Task.Wait(), než se daná úloha dokončí, ale výsledkem toho je zamrznutí celé aplikace, jelikož Monogame potřebuje v hlavním vlákně vykonávat 60x za vteřinu metody Update a Draw (které samozřejmě nemůže vykonávat, když čeká na dokončení jiné úlohy - ve které je nekonečný cyklus) -aspon tak jsem to pochopil

Můžu se pomocí události vrátit z nového vlákna do hlavního vlákna?

Nahlásit jako SPAM
IP: 62.141.28.–
Kubas1290
Stálý člen
3. 8. 2021   #10
-
0
-

#7 Mutagen
Zkusil jsem použít eventy, ale vypadá to, že stále jsou v tom samém vlákně, ve kterém se volají, ikdyž jejich definice probíhá v hlavním vlákně. Jdu se podívat na internet snad něco užitečného najdu co mi pomůže :-)

Nahlásit jako SPAM
IP: 62.141.28.–
3. 8. 2021   #11
-
0
-

Musíš na Task čekat asynchronně, hledej klíčová slova async, await.

Kdyby sis prostudoval nabídnutý setiál, věděl bys. Takto jsi odsouzený k tápání.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Kubas1290
Stálý člen
3. 8. 2021   #12
-
0
-

#11 hlucheucho
nechce se mi za to platit :D

Nahlásit jako SPAM
IP: 62.141.28.–
Kit+15
Guru
3. 8. 2021   #13
-
0
-
Nahlásit jako SPAM
IP: 213.175.51.–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
3. 8. 2021   #14
-
0
-

Know How není zadarmo. A než se zbytečně nadřít, to raději těch pár stovek obětuju. Navíc jednou zaplatíš a máš přístup napořád, můžeš to používat jako pomůcku při programování. A když v ušetřeném čase půjdeš na brigádu, investované peníze se rychle vrátí. Pokud sníš o kariéře C# .NET programátora, tak tuto investici považuji za nezbytnou.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Kubas1290
Stálý člen
3. 8. 2021   #15
-
0
-

Jasně no, ale tak na netu se dají stejné ne-li přehlednější informace najít i zadarmo, jen teda nevýhoda toho je, že je to většinou v aj. 

Třeba tady jsem našel, že je  možné přepínat mezi vlákny pomocí tohoto kodu:

  //switch to UI thread
  this.Invoke((MethodInvoker)delegate {
    // this bit runs on the UI thread
    this.Text = newText;

Akorát teda tomu kodu moc nerozumím. Když ten svůj kod mám ve statické třídě, tak ani this použít nemůžu, jelikož statická třída ani  nemůže vytvářet další instance. Nevysvětlil by mi tu prosím někdo tento kus kodu co provádí? 

Díky moc :-)

Případně jsem ho vzal odsud:

https://social.msdn.microsoft.com/Forums/vstudio/en-US/447970ba-1384-4b07-9566-395dad9db90d/crossthread-operation-not-valid-control-accessed-from-a-thread-other-than-the-thread-it-was?forum=csharpgeneral

Nahlásit jako SPAM
IP: 62.141.28.–
Kit+15
Guru
3. 8. 2021   #16
-
0
-

#15 Kubas129
Kdo za to může, že používáš statické třídy? Je to nešvar, kterého by ses měl zbavit, protože nepřináší žádné výhody a degraduje OOP na strukturované programování.

Nahlásit jako SPAM
IP: 213.175.51.–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
Kubas1290
Stálý člen
3. 8. 2021   #17
-
0
-

#16 Kit
ale tak přece, když vím že tuto třídu použiji jen jednou a nebudu vytvářet žádnou instanci, tak použití statické třídy se jeví jako dobré řešení ne? Například  Board máme jen jednu hrací desku, takže proč ne static Board?

Nahlásit jako SPAM
IP: 62.141.28.–
3. 8. 2021   #18
-
0
-

Když si budeš číst dokumentaci Microsoftu každý večer před spaním, tak to budeš mít i zadarmo a dokonce česky (akorát strojový překlad není úplně ideální). Tento studijní materiál mi příjde pro začátečníka těžký.

Lpění na statické třídě mi příjde absurdní. Pořád si říkám, že je špatně koncepce a z toho pak vyplývají zbytečné problémy. Dobře navržený objektový koncept aplikace ušetří hromadu práce. Dobře promyslet k čemu který objekt je, co dělá, jaké jsou vztahy mezi objekty a pak teprve programovat.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Kubas1290
Stálý člen
3. 8. 2021   #19
-
0
-

#18 hlucheucho
Je pravda, že to moc dobře naprogramovaný nemám, ale nvm jak to vymyslet lépe.

Nyní to mám tak, že hlavní tok programu spouští v Lobby nové vlákno, které se každých 300 ms zeptá serveru jestli v Lobby přibyli noví hráči a pokud ano, tak je vypíše do ListBoxu a zároven se taky ptá serveru, jestli master hráč hru spustil a pokud ano, tak přepne na nový stav hry, ve kterém se vykreslí hrací deska.

Problém je, ale že od této chvíle hlavní hra běží v novém vláknu, takže bych to potřeboval opět dostat do hlavního vlákna.. nějak :D 

Nahlásit jako SPAM
IP: 62.141.28.–
3. 8. 2021   #20
-
0
-

A proč jo? Když tvůj přístup použiju u měření teplot, tak převodník mám taky jeden, takže bude static. A když za mnou za rok příjdou, že těch teplot je třeba měřit víc a budu potřebovat druhý převodník? Nebo když budu potřebovat to použít jako muster pro jinou aplikaci s více převodníky? Když převodník nebude static, půjde udělat jakýkoliv počet instancí, pak každou další podobnou aplikaci dělám z polotovaru. I ta změna aplikace bude snažší.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Kit+15
Guru
3. 8. 2021   #21
-
0
-

#17 Kubas129
Ne. Statické třídy nemají opodstatnění. Přicházíš tím o nejvýznamnější vlastnosti OOP.

Nahlásit jako SPAM
IP: 213.175.51.–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
Kit+15
Guru
3. 8. 2021   #22
-
0
-

#19 Kubas129
Kdybys to dělal přes Observer, tak nemusíš každých 300 ms vytvářet vlákno a dotazovat se na nové uživatele. Vytvoří se až když bude potřebné. Jenže se statikou to neuděláš.

Nahlásit jako SPAM
IP: 213.175.51.–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
Kubas1290
Stálý člen
3. 8. 2021   #23
-
0
-

#22 Kit
a jak to funguje?

Nahlásit jako SPAM
IP: 62.141.28.–
3. 8. 2021   #24
-
0
-

V GUI lze prvidelný dotaz vytvořit snadno pomocí časovače (třída Timer). Na tiknutí časovače (např každých 300ms) pošleš dotaz na server. Pokud odeslání čehokoliv na server by zdržovalo GUI od práce, vždy spustíš Task a necháš ho to udělat na pozadí. Pokud budeš čekat na Task asynchronně, po skončení Tasku můžeš jeho návratovou hodnotu (= stav hry vrácený serverem) zapsat do GUI.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Kubas1290
Stálý člen
3. 8. 2021   #25
-
0
-

#24 hlucheucho
super díky moc :-) S tím timerem to funguje jak má :-)

Jen si říkám, bude to to jedno vlákno stíhat? Nebo jak funguje ten Timer, když jsem to napsal takto:

            System.Timers.Timer timer = new System.Timers.Timer(500);
            timer.Elapsed += checking();      

To pořád probíhá v tom jednom vlákně s tím, že se každých 500 ms zavolá metoda checking že jo? :-)

   

Nahlásit jako SPAM
IP: 62.141.28.–
Kit+15
Guru
3. 8. 2021   #26
-
+1
-
Zajímavé

#23 Kubas129
Vytvoříš vlákno a zaregistruješ ho u správcem účtů. Ten si ho zařadí do seznamu abonentů. Při vytvoření nového uživatele upozorní všechny abonenty, že byl někdo přidán.

Dá se to udělat i přes semafory.

Nahlásit jako SPAM
IP: 213.175.51.–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
3. 8. 2021   #27
-
0
-

Možná by bylo nejlepší to udělat jako webovou aplikaci v ASP .NET s použitím SignalR. Stačí trochu poupravit kód pro chat: hráč pošle svou akci na server (pošli jednomu) a server všem ostatním rozešle nový stav hry (pošli všem). Při příchodu nebo odchodu ve skupině se volají události skupiny a tak lze snadno rozeslat všem info o změně. Současně lze mít na serveru více skupin, které hrají nezávisle na sobě nebo je možné udělat i to, že skupiny (tedy týmy) hrají proti sobě.

Jako bonus: je jedno, jaký má hráč OS, u klienta to běží v internetovém prohlížeči a tak se nemusí nic instalovat. Navíc to může běžet na chytrém telefonu. Při použití jiné šablony můžeš mít rovnou i registraci hráčů, snadno získáš i vícestupňové ověřování uživatele pomocí mailu, sms .... A ke každému uživateli pak i vést statistiky.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
3. 8. 2021   #28
-
0
-

#25 Kubas129
Když v obsluze Elapsed vytvoříš a spustíš Task, provede se to v jiném vlákně. Když bude Event Handler async, tak pomocí await provedeš asynchronní čekání (bez blokování vlákna) na dokončení Task a po jeho dokončení zapíšeš návratovou hodnotu do GUI.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Kubas1290
Stálý člen
3. 8. 2021   #29
-
0
-

#27 hlucheucho
jo to zní fajn, jen škoda že ASP neumím napsat ani čárku :D

Ale co se týče těch statistik, tak mohl bych se na začátku připojit k nějaké databázce s tím, že by si uživatel, tam vždy musel založit nějaký účet a přihlašovat se pak následně na něj

Nahlásit jako SPAM
IP: 62.141.28.–
3. 8. 2021   #30
-
0
-

#29 Kubas129
U webových aplikací je databáze nutností. Webový server si stav jednotlivých klientů nepamatuje, buď mu to klient sám na sebe práskne (např. pomocí cookies) nebo si to server musí někam zapsat (nejčastěji databáze).

Kurz ASP najdeš taky ny itnetwork. Doporučuji zvolit architekturu MVC, je modernější, nebo nejmodernější MVC Core. O WebForms se povídá, že brzy zanikne.

Výhodou použítí ASP .NET šablon je, že dostaneš správu uživatelů "naservírovanou až pod nos". Šablony jsou součástí Visual Studia. Pokud jsi jednotlivec, můžeš získat bezplatnou Community Edition.

Je potřeba dobře znát OOP, nebát se dynamických instancí (nevybavuji si, že bych tam slovíčko static potřeboval).

Zajímavou vlastností knihovny SignalR je, že ji lze použít i pro komunikaci s .NET desktopovou aplikací a tak lze vytvořit webovou aplikaci ovládající nějaký hardware.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Kubas1290
Stálý člen
3. 8. 2021   #31
-
0
-

#30 hlucheucho
není MVC zkratka pro architekturu Model - View - Controller?

Nahlásit jako SPAM
IP: 62.141.28.–
Kubas1290
Stálý člen
3. 8. 2021   #32
-
0
-

Se ale koukám, že je potřeba si pro .ASP založit nový typ aplikace ASP.NET Web Application, to asi nejde přidat do Monogames jako další knihovnu?

Nahlásit jako SPAM
IP: 62.141.28.–
Kubas1290
Stálý člen
3. 8. 2021   #33
-
0
-

#32 Kubas129
vypadá to dost zajímavě, navíc určitě by bylo lepší tu hru mít na webu než-li jako aplikaci, která by se musela stahovat, ale na to mi chybí znalosti krom toho asi by to nešlo propojit s MonoGame.

Nahlásit jako SPAM
IP: 62.141.28.–
Kubas1290
Stálý člen
3. 8. 2021   #34
-
0
-
Nahlásit jako SPAM
IP: 62.141.28.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 22 hostů

Podobná vlákna

Not Valid! — založil pawlik

Cross site scripting — založil Anonymní uživatel

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý