Změny TForm.Handle – Delphi – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Změny TForm.Handle – Delphi – Fórum – Programujte.comZměny TForm.Handle – Delphi – Fórum – Programujte.com

 

Sniper
~ Anonymní uživatel
215 příspěvků
9. 11. 2010   #1
-
0
-

Zdravím
Potřebuji poradit, a také jestli někdo může potvrdit že následující je normální nebo mám něco někde špatně. Jde o to že při změně určitých parametrů formu (např. Position, BorderStyle, FormStyle, ...) za chodu, se také změní jeho handle.
Potřebuji to protože mi na pozadí běží pár vláken které na handle daného okna posílají zprávy (pomocí PostMessage), tento handle zadám jako property daných vláken před jejich spuštěním, takže pokud se za běhu změní tyto parametry (a jakože se změní), tak vlákna dál posílají zprávy na špatný handle => nefunkční program (nemůžu si dovolit aby se "ztratila" byť jediná zpráva).
A nějak nevím jak toto vyřešit. Přemýšlel jsem o následujícím:
Změnit property daného vlákna když měním form, ale nemám jistotu že mezi tím než získám nový handle a předám ho vláknu toto vlákno nepošle zprávu blbě. A navíc nejsem takový znalec, takže nevím jestli je změna property vlákna za běhu thread-safe, pokud je definovaná jen takto:

property SendToWnd: Cardinal read thrSendToWnd write thrSendToWnd;

Případně zároveň s tím můžu udělat cyklus který bude zprávu posílat tak dlouho dokud nedorazí, nebo to změním na SendMessage a budu kontrolovat návratovou hodnotu. Ale tím ty vlákna můžu zbrzdit, což se mi moc nechce.
Nebo taky můžu vláknům předhodit jako property přímo ten form, něco ve stylu:
property SendToWnd: TForm read thrSendToWnd write thrSendToWnd;

Ale tady zase nevím jestli číst handle okna je bez synchronizace bezpečné (asi ne když se mění, což...)?
Napadají mě i další řešení a jejich kombinace, ale ani u jednoho nevím jestli je thread-safe.

Snad jsem se vyjádřil srozumitelně.
Předem děkuji za radu nebo postrčení správným směrem a za potvrzení/vyvrácení zmíněného chování.

Nahlásit jako SPAM
IP: 90.179.201.–
liborb
~ Redaktor
+18
Guru
9. 11. 2010   #2
-
0
-

Změna handle není nic nekalého, ale nejedná se o změnu handle, ale o vytvoření nového okna. Když se podíváš přes Spy++ třeba na vnitřní okno Notepadu a změníš styl Formát -> Zalamování řádků, tak se prostě udělá nové okno s původním obsah v jiném formátu. Ovšem mění se nějaké vnitřní okno, nikoliv hlavní okno, to jsem zatím nikde nepostřehnul :).

V podstatě se můžeš odpíchnout od ID procesu, které se snad nemění :).

Přes API funkce GetTopWindow, GetNextWindow a GetWindowThreadProcessId zjistíš, které HWND patří k tvému procesu a tak můžeš detekovat změnu.

To je taková "hardcore" možnost. Ještě bych se podíval, jestli máš ten form v moci, tak zkusit předat místo handle referenci na něj, jestli by ses nedostal vždy k platnému handle.

Nahlásit jako SPAM
IP: 78.80.52.–
Sniper
~ Anonymní uživatel
215 příspěvků
9. 11. 2010   #3
-
0
-

Za to objasnění okolo handlu díky. Nikdy jsem to nepotřeboval tak to neznám - holt jsem amatér no.

Popíšu to trochu blíže, aby bylo jasnější jak to vypadá.
Program má od počátku skryté hlavní okno (resp. Application.ShowMainForm := False), a okno o které se jedná (mění se mu handle) je SplashScreen. SplashScreen se animuje, a to pomocí jednoho vlákna běžícího na pozadí, no a tohle vlákno mu mění zmíněné vlastnosti podle potřeby pro animaci (samozřejmě používám Synchronize()). Mimo toho na pozadí běží několik (prozatím 2) vláken které načítají a zpracovávají mračna dat potřebných pro "start" programu (tj. zobrazení hl. okna). A tyhle vlákna přeposílají pomocí zpráv svůj stav splash oknu. To je zpracovává a nějak na ně reaguje - mimo jiného tím že vláknu které má na starosti animaci řekne že je vše načteno a má se animovat FadeOut (postupné zmizení splash okna) a zobrazit hlavní okno. No a pokud tyhle zprávy neobdrží tak je jasné jak to skončí - splash zůstane viset na obrazovce navěky.
A teď proč nekontroluji přímo jestli doběhly vlákna načítající data (např pomocí WaitforMultipleObjects, WaitFor, ...) - protože vlákno řídící animaci musí být na těchto "načítacích" vláknech zcela nezávislé (nesmí na ně nijak odkazovat, ani se spoléhat na nějaké příchozí údaje), a splash okno nesmí na něčem takovém zamrznout.
Pracovat s PID mi přijde opravdu už moc hardcore (ale problémy by mi to asi ani nedělalo, znám to).
Jak vyplývá z předchozího - okno mám v plné moci, ale vlákna si běží každé na svém písečku takže bych z nich nerad lezl do VCL, ale jako poslední možnost... - může být že bych tam hodil nějakou proceduru co by načítala aktuální handle a tu volal v Synchronize() pokud návratová hodnota SendMessage nebude sedět.

Jinak ať tu zbytečně nepíšu trachtáty - je změnění property a tím i nějaké vnitřní proměnné vlákna za běhu thread-safe nebo není?

Nahlásit jako SPAM
IP: 90.179.201.–
liborb
~ Redaktor
+18
Guru
9. 11. 2010   #4
-
0
-

Sniper napsal:je změnění property a tím i nějaké vnitřní proměnné vlákna za běhu thread-safe nebo není?



Pro čtení určitě, samozřejmě to můžeš vyřešit zámkem (třeba přes semafor), ale detaily Delphi implementace neznám. Buď bude vědět někdo jiný nebo se obrať na strejdu googla :).

Kdybych toto měl řešit a handle se mi měnil, tak se na něj asi vybodnu a pasíruju data jinak. Pokud by to mělo být opravdu nezávislé, tak bych to řešil přes soket a UDP pakety. Na takovéto věci - nezávislé předávání dat - výborná věc.

Nahlásit jako SPAM
IP: 78.80.52.–
Sniper
~ Anonymní uživatel
215 příspěvků
9. 11. 2010   #5
-
0
-

No nevim, kvůli předání jednoho čísla mezi vlákny jednoho procesu používat síťový záležitosti to se mi zdá trochu moc. Na to tu mám globální proměnné a kritické sekce, a mezi procesy se mi osvědčilo použití pojmenovaných MemoryMappedFile a mutexů (i sem si na to sepsal třídu).
Zatím to řeším tak, že v načítacích vláknech jsem nahradil PostMessage za SendMessage (posílám na splash okno), a pokud tato nevrátí očekávaný výsledek, tak znovu načtu handle splash okna (referenci na něj zadávám při vytvoření vlákna), samozřejmě uvnitř Synchronize(), a pak opakuji odeslání (resp. ho opakuji dokud není úspěšné - tady bych to možná mohl omezit na určitý počet, kdyby se něco po..., abych neodesílal donekonečna). Zní to možná blbě, ale už jsem napsal větší zvěrstva, a zatím to, zdá se, funguje.
Jináč to splash okno tam v zásadě funguje jako řídící prvek pro všechny vlákna.

Ale pokud má kdokoliv jiný návrh řešení, rád se přiučím.

Nahlásit jako SPAM
IP: 90.179.201.–
liborb
~ Redaktor
+18
Guru
9. 11. 2010   #6
-
0
-

Jsou lidi, co předávají jakákoliv data přes soket. Ono to má totiž jednu výhodu, a to tu, že je to buď zabezpečený přenos (zpráva vždy dorazí - TCP) nebo "nezávislý" přenos a klidně i z více míst najednou bez potvrzení (UDP). Z určitého pohledu je to i lepší než globální proměnná, sdílená paměť apod. Ale jinak je to pořád to samé (soket, pipe, paměť ....).

V podstatě to řešíš dobře, jenom pozor na to, že SendMessage je blokující. Možná by bylo lepší nejdříve handle testovat (IsWindow), jestli je to pořád ještě okno.

A další možností je, aby si splash screen chodil pro ty data do těch oken sám - těm se asi handle nemění .... ;)

Nahlásit jako SPAM
IP: 78.80.52.–
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, 11 hostů

Podobná vlákna

Práce s více TForm — založil S.Salomon

Co je HANDLE ? — založil Martin

Příkaz Handle — založil Paulí

 

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