Gif animate

mercoledì 31 agosto 2011 - 13.06
Tag Elenco Tags  C#

pelling10 Profilo | Junior Member

Salve a tutti!!!
Ho un semplice progetto in c# in cui ho una picturebox con dentro un immagine gif animata che funziona perfettamente, e poi ho un bottone dove al click eseguo un suono usando la classe SoundPlayer in modo asincrono (PlaySync).
Il problema è che quando clicco sul bottone parte il suono ma l'immagine gif si ferma per tuta la durata del suono. Questo chiaramente perche PlaySync esegue il suono bloccando tutto il resto.
Volevo sapere se utilizzando sempre PlaySync per eseguire il suono posso non far bloccare la giff animata.
Grazie

u235 Profilo | Junior Member

quel metodo è sincrono... basta che usi Play() anzichè PlaySync()

pelling10 Profilo | Junior Member

Grazie per la tempestiva risposta!!!
Purtroppo devo usare PlaySync() perchè devo attendere la fine del suono per effettuare altri controlli.
Quindi volevo sapere come fare in modo che la gif continui ad essere animata durante il PlaySync()

u235 Profilo | Junior Member

ciao, oggi sono di cazzeggio, quindi sto girovagando per i forum ad imparare! :)

hai provato a fare come ti ho postato nell'altro post? ovvevo usare un thread separato? il playSync lo mandi su un thread a se, in modo che il thread principale vada avanti.

pelling10 Profilo | Junior Member

Ciao, grazie per la risposta!!!!
e se provassi a lanciare la gif animata in un thread a se?

u235 Profilo | Junior Member

credo di aver capito cosa vuoi fare... si tratta di preload, giusto?

comunque dipende da come stai gestendo la cosa, se nel thread principale della form ci sono i controlli (tra cui la picturebox con la gif) non puoi fermarlo, bloccheresti anche la gif che è sotto il controllo del thread principale. Caso diverso è se la esegui su un form separato. Ad esempio, potresti rendere invisibile la form che lavora con playSync e aprirne una nuova con la gif, per poi chiuderla e rendere di nuovo visibile il form quando arriva alla fine della procedura.

in poche parole :

rendi il form invisibile (ma anche no! visualizzi sotto);
apri la seconda form con la gif (anche senza bordi ecc.);
esegui tutta la procedura nella prima form (suoni ecc. e nel frattempo vedi la gif sul secondo form);
rendi visibile la form(...);
chiudi la form secondaria;

comunque se vuoi un buon consiglio dovresti mostrare il codice, solo così potrei consigliarti bene.
ad esempio mi domando perchè non vuoi eseguire il playSync su un thread secondario, perchè non lo vuoi esegure con play, come e perchè viene richiamato questo blocco di codice sincrono... insomma, racconta un pò, tranquillo, ti prometto che non ti frego l'idea!

ciao.

pelling10 Profilo | Junior Member

Praticamente sto eseguendo una specie di guida parlante;
Quindi in una form ho da un lato l'immagine gif con l'omino che parla e dall'altro una serie di bottoni.
Cliccando su questi bottoni rendo visibile la gif animata ed eseguo il suono con playSinc() (dando l'impressione che sia l'omino della gif a parlare) alla fine di questo suono ne seguono altri.
Con playSinc() riesco a gestire il concatenamento dei suoni ma la gif resta bloccata per tutti i suoni che eseguo.
Con il codice che tu mi hai postato riesco a fare cio che voglio, ma nel caso in cui al click del bottone devo eseguire non solo un suono ma una serie di suoni, parte il primo suono, la gif continua a girare e poi gli altri suoni che susseguono non riesco a startarli.

Dove sbaglio?

GRAZIE MILLE SEI SEMPRE GENTILE!!!!!

u235 Profilo | Junior Member

ok, adesso è un pò più chiaro... io comunque trovo che sarebbe stato più appropriato l'uso di wpf, sai per le animazioni... comunque tornando altuo problema :
passa una lista di percorsi wav e li esegui uno dietro l'altro in modo asincrono su thread separato.

esempio :
void PlayWav(object objPercorsiWav) { string[] PercorsiWav = objPercorsiWav as string[]; SoundPlayer simpleSound = new SoundPlayer(); foreach (string percorso in PercorsiWav) { simpleSound.SoundLocation = percorso; simpleSound.PlaySync(); } } void PlayWavAsync(string[] PercorsiWav) { Thread t = new Thread(PlayWav); t.Start(PercorsiWav); }

in questo caso basta che usi PlayWavAsync(new string[] { @"C:\Windows\Media\chimes.wav", @"C:\Windows\Media\chimes.wav"}); e vedrai che funziona! se invece usi direttamente PlayWav(new string[] { @"C:\Windows\Media\chimes.wav", @"C:\Windows\Media\chimes.wav"}); allora si blocca l'esecuzione del thread principale (gif bloccata)
ciao.

pelling10 Profilo | Junior Member

SEI MITICO!!!!!!! GRAZIE!!!!!!!!!
ho fatto cosi:

void PlayWav(object objPercorsiWav)
{
string[] PercorsiWav = objPercorsiWav as string[];
SoundPlayer simpleSound = new SoundPlayer();
foreach (string percorso in PercorsiWav)
{
simpleSound.SoundLocation = percorso;
simpleSound.PlaySync();
}
}

void Parla(string[] PercorsiWav)
{
pictureBox2.Visible = true; // visualizzo la gif animata
pictureBox2.Refresh();
Thread t = new Thread(PlayWav);
t.Start(PercorsiWav);
}

Chiamata: Parla(new string[] { Application.StartupPath + @"\voice\022_Ciao amico.wav"});

Funziona tutto alla perfezione!!! solo una cosa quando smette di parlare come faccio a nascondere la gif animata?

u235 Profilo | Junior Member

Ciao, devi aggiungere alla fine del ciclo una chiamata ad un metodo (oppure usi gli eventi, ma in questo caso non credo ci sia bisogno) che rende la picturebox.visibile a false, per farlo però hai bisogno di un piccolo accorgimento :
dato che la chiamata poterbbe avvenire da un thread diverso (nel tuo caso si perchè usi PlayWavAsync), il metodo ti potrebbe dare un errore perchè tenti di accedere ad un controllo, quindi devi controllare che la proprietà InvokeRequired, e nel caso sia true, chiamare il metodo stesso attraverso un delegato, invece in caso sia false, modifichi i controlli a tuo piacimento. Richiamare lo stesso metoto con un delegato, fa in modo che alla seconda chiamata InvokeRequired sia false, quindi avviene normalmente la madifica senza errori.

comunque per spiegarmi meglio ti posto il codice :

void PlayWav(object objPercorsiWav) { string[] PercorsiWav = objPercorsiWav as string[]; SoundPlayer simpleSound = new SoundPlayer(); foreach (string percorso in PercorsiWav) { simpleSound.SoundLocation = percorso; simpleSound.PlaySync(); } FineWav(); } private void FineWav() { if (this.InvokeRequired) this.Invoke(new CrossAppDomainDelegate(FineWav)); else this.pictureBox2.Visible = false; } void PlayWavAsync(string[] PercorsiWav) { Thread t = new Thread(PlayWav); t.Start(PercorsiWav); }

ciao.

pelling10 Profilo | Junior Member

Grazie lo provo e ti faccio sapere!!!!!

u235 Profilo | Junior Member

Certo...

Ciao.

pelling10 Profilo | Junior Member

Ho provato il l'esempio di codice che mi hai postato..... FUNZIONA BENISSIMO :-)!!!!!!! GRAZIE!!!!!
Potresti ora spiegarmi come caricare in una picturebox una gif animata in un thread separato?
GRAZIE!!!!!!!

u235 Profilo | Junior Member

ciao, non è possibile e la cosa non avrebbe nessun senso, si tratta di un controllo che deve stare dentro il thread principale, al massimo puoi aprirla in un nuovo form separato da quello principale, ma non vedo l'utilità...

quando usi thread separati devi lasciare sempre libero il thread principale con i controlli, esso infatti deve sempre tenere il "controllo del programma" svolto su di esso, se si rende necessaria la separazione dei thread, allora questa deve avenire lanciando le operazioni "secondarie" su altri thread, in modo da lasciare libero il thread principale (che eventualmente controlla altri thread) con i controlli.

Non abusare dei thread, ricorda che in certe situazioni ti potresti trovare brutte sorprese... a volte si rende necessaria la sincronizzazione tra loro, e potresti anche trovarti ad avere un accesso incoerente alle risorse condivise con comportamenti che non ti aspetti di sicuro!
spesso gestirli ti incasina la vita, vacci piano...
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5