Newsgroup: it.comp.lang.visual-basic
Titolo: Eseguire operazioni su thread principale (VB2008)

Ciao a tutti,
invio questo messaggio anche ad un altro ng.. per quelli che leggono 
entrambi, non offendetevi :-)
In una applicazione VB2008, creo un oggetto che si prende carico di creare 
dei grafi DirectShow e di mandare in play dei filmati, e il device di uscita 
e' una scheda apposita.
Mi accorgo pero' che l'applicazione si comporta in maniera differente nel 
caso in cui il "segnale di partenza" arrivi da un Button nella form 
principale,  oppure da un evento scatenato da un oggetto che aspetta i 
comandi in tcp.
Provo a fare un esempio....
Dim MioOggetto as new MiaClasse ' la classe che si occupa delle operazioni 
sui filmati
Private Sub Button1_Click (....) Handles Button1.Click
    Test
End Sub
Protected Overrides Sub ElaborateMessage(ByVal Message As 
System.Xml.XmlDocument)
    Test
End Sub
Il metodo ElaborateMessage viene definito come MustOverride nella classe 
base dell'oggetto che ascolta i messaggi. Questo metodo viene chiamato 
quando viene riconosciuto un messaggio valido.
Nell'infrastruttura sotostante, e' presente un oggetto manager che alza un 
evento quando riceve un messaggio e passa come argomento il contenuto del 
messaggio stesso.
Private Sub Test ()
MioOggetto.Play
End sub
Come dicevo prima, ho degli effetti differenti se il metodo Test viene 
chiamato tramite la pressione del Button1 sulla form, oppure se viene 
chiamato dall'elaborazione del messaggio in arrivo.
Intuitivamente credo che questo comportamento sia dovuto al fatto che i due 
Thread siano differenti, e vorrei sapere se c'e' un modo per far si che 
entrambi i metodi agissero sul medesimo Thread (quello principale, 
immagino).
Ho provato a istanziare un oggetto di tipo
System.Threading.SynchronizationContext
ed ad utilizzarne il metodo send nell'elaborazione dei messaggi di rete, ma 
non e' cambiato nulla.
Come posso agire?
Grazie... Maurizio

 wrote:
....con tutta la buona volontà del mondo....e anche accendendo la
palla di cristallo alla massima potenza.....
definire "effetti diversi" per cortesia!
Viene invocata o no questa subroutine?
Se si....gli "effetti" diversi dipenderanno da essa...mi pare logico!
Dipenderà probabilmente anche dal contesto....casomai  l'handles del
button ha già la new e le inizializzazioni fatte...e casomai se è già
stata usata anche una serie di variabili valorizzate!
L'evento che "alza" molto probabilmente non trovva qualcosa
valorizzato...ricorda che è "cura" tua gestire inizializzazioni prima
invocazione...e invocazioni successive!

Non sono un esperto in thread ma mi sembra di capire che il problema possa 
essere nel fato che la tua applicazione non � thread safe, prova a vedere se 
qui trovi qualcosa per renderla thread safe.
http://msdn.microsoft.com/it-it/library/ms171728.aspx

definire "effetti diversi" per cortesia!
...
Te la sei voluta tu eh! :-)
1) All'avvio della applicazione, creo un grafo di filtri, utilizzando tra 
l'altro il GMFBridge e passando, prima di creare il grafo in maniera 
"intelligente", dei filtri di una scheda di tv-output
2a) Premendo l'apposito tastino button1 sulla form, invoco la routine [Test] 
che passa al grafo la mia clip da far girare, chiama il play della clip 
stessa, e sul mio secondo monitor, quello cioe' collegato alla scheda 
tv-output, vedo il filmatino.
2b) Intercettando un messaggio che mi arriva da socket (un oggetto mi alza 
un evento di ricezione messaggio), invoco la routine [Test] che   passa al 
grafo la mia clip da far girare, chiama il play della clip stessa, e sul mio 
secondo monitor non vedo un piffero, mentre la clip va in play su una 
finestra del mio monitor principale
A naso, imputo questo comportamento ai differenti thread che vengono 
chiamati in causa.
Le condizioni di partenza sono le stesse, l'applicazione e' unica, la 
routine e' la stessa per tutti e due e viene invocata correttamente. 

 
http://msdn.microsoft.com/it-it/library/ms171728.aspx
...
Gli do un occhio, grazie

Aggiungo....
sto facendo delle prove per vedere se puo' essere corretto quello che ho in 
mente.
ho aggiunto queste righe alla procedura New della classe che gestisce il 
play, per verificare i sospetti
Public Sub New
Dim TH As System.Threading.Thread = System.Threading.Thread.CurrentThread
Debug.Print( TH.GetHashCode.ToString)
TH = Nothing
....
End Sub
Quello che ho voluto fare e', leggendo il codice di Hash del thread 
lanciato, se questo thread e' lo stesso che manda in play la clip (dato che 
analogamente, ho riportato lo stesso codice anche nella procedura che manda 
la clip)
Creo l'oggetto, e il codice di hash del thread corrente e' 10 (ad esempio)
Se mando la clip premendo il Button1 della form, la procedura che mette in 
play la clip, riporta come codice di hash del thread, sempre 10.
Se mando la clip tramite l'evento alzato dal socket, il codice di hash del 
thread cambia (ad es. 12)
Ripeto pero' che la routine [Test] e' la stessa (non uguale, proprio la 
stessa), ma cambia il thread entro cui viene lanciata.
Speravo di risolvere usando un oggetto di tipo
System.Threading.SynchronizationContext, ma, o non serve al caso mio, oppure 
non lo utilizzo nella maniera corretta.
Chi mi aiuta?
Grazie... Maurizio

Ma la funzione Test usa dei dati generali o condivisi che pesca da qualche 
parte?
E' possibile che quando arriva il messaggio dal socket crei un'altra istanza 
con dati diversi e quindi si giustifica il comportamento diverso?
Se la routine � indipendente che tu la chiami dal thread principale o da 
altri non vedo cosa possa cambiare, sarebbe come dire che se faccio una 
funzione che calcola 3+2 se la chiamo in modo diretto fa 5 ma se la chiama 
un thread diverso fa 6.
Oppure ci sono degli eventi da gestire che per� nel caso di chiamate da 
thread diversi non vengono sollevati e qundi non vengono gestiti?
Secondo me ci sono dei parametri diversi nei due casi, non riesci in sede di 
debug controllare tutti i parametri richiesti dalla funzione Test e 
confrontare i due casi?

 parte?
...
La funzione test chiama un metodo in un oggetto istanziato, cioe':
Private Sub Test ()
    MioOggetto.MioMetodo
End Sub
Natutalmente l'oggetto MioOggetto e' un'istanza di una classe, dichiarata a 
livello della classe chiamante (quella, per intenderci, dove c'e' il metodo 
Test).
Naturalmente ho confrontato i due casi e, a parte il thread differente, non 
c'e' niente che possa far pensare ad una differenza comportamentale.
Quello che invece mi fa pensare che sia proprio il differente thread a 
portare a risultati differenti, e' che effettivamente il DirectShow e' 
abbastanza influenzabile dai Thread chiamanti. Quello che mi servirebbe, 
come tentativo, e' il poter comandare il MioOggetto, sempre dallo stesso 
thread. Per far questo sto pensando di utilizzare una Queue da andare 
periodicamente a consultare e andare a vedere se ci sono comandi da inviare 
a MioOggetto.
Naturalmente l'interrogazione della Queue avverrebbe sempre dallo stesso 
Thread.
Come si dice qui... "mo provo" :-)
Anzi, mi sa che ci vuole domani, per ora ho altre cosucce da fare.
In ogni caso, altri eventuali suggerimenti sono piu' che ben accetti!!
Ciao... Maurizio 

Cosa faccia DirecShow sotto poi chi lo sa, pu� essere che ci sia un 
controllo sui thread per cui non funziona come ti aspetti.
Hai provato a forzare la chiamata di Test dallo stesso thread ad esempio non 
richiamando Test direttamente dagli eventi del socket (che sicuramente sono 
generati da altri thread) ma ad esempio attivado un timer su form.
Oppure nel link che ti avevo postato c'era appunto un esempio su come 
riportare la chiamata al thread principale del form.

 riportare la chiamata al thread principale del form.
...
Infatti.
Mi sa che un buon metodo sia quello di implementare l'interfaccia 
ISynchronizeInvoke e quindi il metodo Invoke.
Il problema e' che non trovo nessun modo per farlo; quasi quasi eredito da 
Control.
Boh 

 wrote:
zac
Cos' tanto ad occhio....
non vedi un piffero perchè l'oggetto è "occupato"!
Finchè un device non è libero non visualizza "altro"
ora....sicuramente....
un thread lo occupa....e non lo rilascia.....
e l'altro thread si accoda!
Soluzione
ti implementi un server che riceve gli stream o quello che sono e ci
pensa lui a farli visualizzare in successione gestenndo conflitti
vari!
A quanto sembra la scheda del socondo monitor non ha dll e/o sw  che
gestiscono il conflitto di chiamate (ha anche una sua logica su schede
economiche....della serie: "spendi poco...??? e allora visualizzo una
cosa per volta e non gestisco nessuna coda! ovvia!"!


wrote:
aggiungo....
cose simili le fa red5...anche lui opportunamente programmato....ed è
un casino abissale (almeno a me odiando java mi è sembrato)
implementare applicazioni di streaming che funzionino ragionevolmente
"sempre"!
Siccome mi sembra che alla fine tu voglia fare una cosa simile...
dacci un occhio!

Cos' tanto ad occhio....
non vedi un piffero perch� l'oggetto � "occupato"!
Finch� un device non � libero non visualizza "altro"
ora....sicuramente....
un thread lo occupa....e non lo rilascia.....
e l'altro thread si accoda!
...
si, credo sia esattamente cio' che succede. Ed il problema e' proprio 
questo.
Mi spiego.Creo una nuova istanza del mio oggettino (che dovrebbe proprio 
essere un server che gestisce i vari stream). Lo faccio con il thread che ha 
come hash code, ad esempio, 10.
Se faccio tutte le operazioni con questo thread, nessun problema.
Se sto prelevando comandi in rete, c'e' naturalmente un oggetto socket 
sottostante (con un suo thread), che quando riceve un comando, alza un 
evento.
Questo evento "gira" sotto un suo thread, ad esempio il 12.
Se gestisco questo evento, lo sto gestendo sul thread 12, quindi qualunque 
comando vado a dare al mio oggetto che gestisce le clip, lo faro' con il 
thread 12, e qui si impalla tutto.
Ecco perche' sto cercando un modo per inviare comandi all'oggetto che 
gestisce le clip, tramite thread principale.
La soluzione potrebbe essere quella di implementare l'interfaccia 
ISynchronizeInvoke ?
Il problema e' che non trovo il modo di farlo, considerando che il mio 
oggettino gestore di clip NON eredita da Control.
Altre idee?
Ciao e grazie ancora... Maurizio 

Non puoi lanciare il tuo clip con thread a parte (senza usare il thread del 
form principale) che crei tu implementando una tua classe apposita che, con 
una adeguata gestione degli errori, abortisce l'esecuzione del clip in corso 
nel caso in cui sia invocata un'altra chiamata, e lasci quindi spazio al 
thread successivo? 

 Finchè un device non è libero non visualizza "altro"

Un comando , fra quelli che hai implementato, che distrugge gli
oggetti/istanze precedenti?
Il problema IMHO è che se tu hai lanciato un filmato....non puoi far
altro che aspettare che esso termini...o forzare tu stesso la fine del
medesimo.
Se forzi la fine del filmato...l'istanza viene distrutta e dopo un
tempo x (non ritorna disponibile subito...meno che meno se usi dll
unmanaged per gestire l'hw!) ritorna disponibile per nuovi filmati!
...puoi pensare di implementare nella classe che gestisce la scheda
una serie di eventi che stoppino la richiesta di visualizzare altri
filmati finchè è occupata....
...dei metodi per terminare la visualizzazione corrente...
....un override del "play filmato" che accetti anche un puntatore alla
zona di memoria riempita dal winsock o da quello che usi (con c# lo
puoi fare...in 
vb.net
 no!...almeno non senza api!)
Se però è un server di streaming....cavolo hai il clone di flash
server che è pure open source!!!...si chiama red5....unica palla....è
scritto in java....ma gira sotto windows e sotto linux (e credo anche
sotto macosx)....
Sotto windows ho usato openmeetings per fare elearning...è anche
quello opensource....e non era proprio malaccio...anche se ha bisogno
ancora di crescere!

Se per� � un server di streaming....cavolo hai il clone di flash
server che � pure open source!!!...si chiama red5....
...
Non so se fa al mio caso (almeno ora), ma me lo segno perche' puo' essermi 
utile in altre cose. :-)
In ogni caso, resta il dilemma.... Come lanciare operazioni su un singolo 
thread.
Forse la soluzione e' esporre tutto a COM.
Non che ne abbia troppa voglia, pero'.
Ora sto provando a mandare tutto con il thread principale tramite l'invoke 
della form principale. A breve i risultati (lo so, mi sono intestardito 
sulla questione thread, ma secondo me la chiave di volta e' quella)


 un'altra chiamata, e lasci quindi spazio al thread successivo?
...
Da quanto sto capendo, il problema e' che non ci devono essere thread 
successivi, ma deve essere lo stesso thread che genera e inserisce clip.
Questo per sfruttare la capacita del GMFBridge di poter avere piu' grafi 
contemporaneamente come sorgenti, e un solo grafo di render.
Ciao e grazie... Maurizio

 Ciao e grazie ancora... Maurizio
Ma stai facendo un "clone-premiere" in 
vb.net
? (brrrrrrr!!!!)
occhio che il thread singolo se lo "infarcisci troppo" poi ha problemi
di prorità e/o  memoria!
rischi di far rallentare troppo tutto o andare in memory exception
....oltrechè non sfruttare i dual/quad core!
Non sò che augurarti....un pò ti capisco....
sei come me che mi sono intestardito a far funzionare Access con
Entity....partita pressochè persa!...ma non demordo!

Non s� che augurarti....un p� ti capisco....
sei come me che mi sono intestardito a far funzionare Access con
Entity....partita pressoch� persa!...ma non demordo!
...
Ah boh, non so neanche di cosa parli!! In bocca al lupo!
