Event v novém vlákně?   zodpovězená otázka

Threading

Dobrý den. Řeším takový problém. ve své aplikaci provádím určité grafické - časově determinované činnosti (např. animace fotek na obrazovce).

K tomu (za pomoci třídy AudioVideo z DirectX) pouštím hudbu.

Bádal jsem dnes několik hodin, jak zajistit, aby se mi událost Audio.ending ošetřila nezávisle na hlavním běhovém vlákně aplikace. O co jde. Pokud mi skončí přehrávání skladby, potřebuji právě odchycením této události spustit metodu, ve které nahraju z disku další skladbu a spustím její přehrávání.

Jenomže ač jsem dělal rozličné pokusy (spouštění audia v jiném threadu,...), vždy jsem dospěl k jednomu- ošetření vzniklé události se provede vždy v hlavním vlákně, tzn. pokud je toto vlákno zaneprázdněno (nemám tam všude např. nasázené doeventsy), tak se přehrávání skladby spustí až ve chvíli uvolnění tohoto vlákna, nebo naopak, pokud tam ty doEventsy nasázím, tak zase naopak dolde k rušivému přerušení animace po dobu, než se ošetří to spuštění nového přehrávání.

Je možno aplikaci nějak donutit, aby to audio včetně ošetření jeho eventů běželo v samostatném vlákně, nebo je ta třída Audio de facto nějaké Controls a jako u většiny ostatních, pokud je vytvořeno v kontextu např. form1 tak i když některé jeho metody spustím do externích vláken, tak ošetření událostí probíhá v hlavním běhovém vlákně rodičovského formuláře?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ještě doplnění.

Jediné, kdy se mi podařilo přiblížit se alespoň částečně požadované funkčnosti (nezávislosti) byl způsob, kdy jsem si tuto třídu nadefinoval a spustil v druhém formuláři, a ten jsem si dle rad z diskuse ve vlákně http://www.vbnet.cz/forum-tema--442-vice... spustil do zcela samostatného vlákna.

Tam jsem ovšem narazil na jiný problém - jednak mám zbytečný (a rušivý) druhý formulář, což by se snad dalo poléčit jeho nastavením na plně průhledný, nebo mimo obrazovku (ani jedno řešení mi ale nepřipadá zcela ideální) ale hlavně se mi zatím nepodařilo najít rozumnou cestu jak to audio zase vypnout. Pokud jsem zavolal abort na vlákno, ve kterém se mi to celé vytvořilo, tak se to vyplo až po dokončení právě přehrávané písničky, a jiné pokusy taky nestály za moc.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Podle toho co píšete to vypadá tak, že si třídy pro přehrávání audia a videa při vytváření instance v konstruktoru skutečně uloží kontext ze kterého byly vytvořeny (v tomto případě WindowsFormsSynchronizationContext) a v tomto kontextu pak vyvolávají veškeré svoje události pomocí Send nebo Post (ve skutečnosti volání metod napojených na události) což se projeví tak, že kód bude prováděn vždy v hlavním vlákně uživatelského rozhraní (což je kontext který instanci třídy vytvořil) což je nežádoucí. Nepomůže ani spuštění dané přehrávací metody ve vlastním vlákně.

Zdá se, že řešení by mohlo být jednoduché: V metodě, která je napojená na událost Ending vytvořte dočasné nové vlákno, které bude provádět metodu která nahraje z disku další skladbu a spustí její přehrávání (i když se mi nezdá že toto by bylo tak náročné aby to nešlo provést v hlavním vlákně). Vlákno bude deklarováno pouze v rámci té metody takže po skončení bude automaticky odstraněno Garbage Collectorem a nebude zabírat systémové prostředky. Tudíž hlavní vlákno zajistí pouze vytvoření dočasného vlákna a jeho spuštění, samotný "náročný" kód se provede v dočasném vlákně - hlavní vlákno uživatelského rozhraní nebude zatíženo.

Pokud to nebude fungovat ani takto, můžeme se pokusit najít jiné řešení.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Děkuju za Vaši pomoc - tímto směrem jsem taky začal uvažovat, jenom musím domyslet všechny souvislosti.

Samozřejmě samotné načtení skladby a její spuštění by nemuselo být časově až tak náročné (pokud není trochu objemnější), ale přece jenom se o nějaké zdržení jedná a pokud přitom zrovna ve fullscreenu přes sebe animuju dvě fotky, tak to zaškobrtnutí je tam patrné - proto vymýšlím, jak to celé zoptimalizovat.

Jinak děkuju hlavně za tu osvětu - to je to, co mi chybí nejvíc. Veškeré publikace se zabývají, řekl bych, vnějšími efekty jednotlivých technologií (vlákna, události, třídy,...), ale velice málo dovolí nahlédnout pod pokličku - jak to vnitřně funguje a hlavně jak je to vnitřně provázané. No a bez toho se dost dobře nic komplexnějšího nedá vytvořit, aby to nebyla sázka do loterie bude-li to fungovat, či nikoliv.

Ale zpátky k mému problému - zkusím si to trochu utřídit v hlavě (nejde o to jak to naprogramovat - to je celkem jednoduché, ale o zvážení celé koncepce, jestli to takto bude plnit účel) a pak to vyzkouším. Zatím ještě jednou dík.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tak jsem to "částečně" vyzkoušel (částečně proto, protože nemohu v tuto hodinu moc nahlas vyhrávat, nanébrž hnedle vedle mého pracoviště spí manželka a nedej bože, aby se probudila - to bych musel od počítače :-), a vypadá to celkem nadějně. Jediné, co budu muset ještě domyslet, že budu muset do všech časově náročnějších akcí na hlavním vlákně nasázet DoEvents, ale myslím, že to nebude zas až takový problém.

Takže ještě jednou díky!

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ještě, pokud mohu, bych se zeptal na jednu drobnost s eventama.

Protože já ve své aplikaci odchytávám těch událostí více a mohou být, samozřejmě, vyvolány i v okamžiku zaneprázdnění vlákna nějakou činností, jak je v .net technologii tato skutečnost ošetřena?

Pokud je vyvolána nějaká událost, pak se spustí,je-li k dispozici, její ošetření.

Pokud je ale součástí tohoto ošetření souvislý programový kód, ve kterém nemám doevents, pak tento kód "vytíží" pracovní vlákno a co se stane s případnými dalšími událostmi, které jsou v této době vyvolány? Existuje nějaký zásobník událostí, do kterého jsou ukládány a ve chvíli, kdy k tomu dám programu příležitost tak se jednotlivé požadavky vyřídí, nebo mají takovéto události platnost pouze určitou dobu a pak samy "vymizí" (doufám že to ne!)?

Ptám se z jednoho prostého důvodu. Mám aplikaci, kterou jse, bohužel z neznalosti, chtěl udělat až příliš dokonalou a protože dělá více různých časově celkem náročných činností, vše řeším v samostatných vláknech. No a celé je to právě řízeno a organizováno prostřednictvím událostí (několik různých časovačů, ukončení nějaké činnosti spustí činnost jinou, atd...) (právě mé současné dotazy jsou vedeny snahou o celkové zjednodušení koncepce, protože fůru činností mohu, dle mých současných znalostí, celkem bez problému a s minimálními omezeními sloučit do jednoho vlákna).

No a právě nyní se mi stává, že se mi celá aplikace po cca 2-3 dnech chodu v tichosti odporoučí (vypne) a já budu muset zjistit, čím to je (mám nějaké kontrolni výpisy chodu aplikace, tak je budu muset zkusit projít, naleznu-li v tom nějaké zákonitosti). A právě jednou z neznámých pro mne je hypotetická možnost, co se tak může stát, kdyby se nějaké dvě události sešly ve stejnou dobu, jestli si s tím systém poradí.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Záleží na tom, zda-li kód který vyvolá událost běží ve vlastním vlákně. Pokud ano, provede se kód událostní metody právě v tom vlákně nezávisle na zaměstnaném hlavním vlákně. Pokud máte na mysli například událost klepnutí na tlačítko, musí se nejprve dokončit zrovna probíhající náročná procedura a teprve potom hlavní vlákno automaticky vyzobe a zpracuje všechny nahromaděné zprávy ze své fronty zpráv (Windows Messages) a vyvolá příslušné události. Každá Windows aplikace má tzv. frontu zpráv, což je zásobník do kterého systém vkládá veškeré akce na systémové úrovni (pohyb myší, klepnutí myší, stisknutí klávesy, viz. http://wiki.winehq.org/List_Of_Windows_M... ) které se můžou do aplikace řítit i rychlostí desítek zpráv za vteřinu. Vy tím voláním DoEvents donutíte aplikaci, že právě teď chcete zpracovat všechny nahromaděné zprávy (výsledný efekt bude vyvolání a zpracování všech událostí ovládacích prvků) a pokud to děláte v cyklu, navozuje to pocit že aplikace žije, ovšem je to za cenu obrovského zpomalení. A zde právě přichází ke slovu vlákno, do kterého náročnou operaci umístíte a hlavní vlákno se bude věnovat pouze zpracování Windows Messages přičemž výsledek bude naprosto plynulé uživatelské rozhraní a nezávisle na něm na pozadí probíhající náročná operace. Bohužel v .NETu jsou takovéto "low-level" záležitosti známé z klasického Win32 programování víceméně naprosto transparentní.

Dvě události ve stejnou dobu jsou vlastně dvě metody probíhající ve stejnou dobu tudíž je to možné pouze v případě, že každá bude běžet ve svém vlákně a budete mít dvou nebo vícejádrový procesor (ale i tak je to velmi malá šance).

Nevím jestli se mi podařilo zodpovědět váš dotaz, kdyžtak se ještě ptejte, případně vám můžu poskytnout svůj Windows Live ID pro okamžitou komunikaci Messengerem.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Ještě jednou Vám moc a moc děkuji - perfektní odpovědi k jádru věci, právě to jsem hledal!

Dík i za nabídku, ale prozatím si myslím, že Vaše odpovědi jsou natolik fundované a obecné, že by mohly být přínosem i pro mnohé další návštěvníky tohoto Webu, a tudíž by ode mne bylo nadmíru sobecké usurpovat si je, použitím soukromého kanálu, pouze pro sebe.

Takže ještě jednou dík - musím jít vydělávat, neb programováním chléb svůj vezdejší nezískávám.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback