Ciao Bart,

Bart Aimar ha scritto:
> Paolo Mantovani ha scritto:
> 
>>>> Questo è il problema vero da risolvere: L'oggetto non si dovrebbe
>>>> perdere
>>> Si... concordo... ma una domanda che comunque riprenderò sotto è: ma se
>>> lo si perde si può ritrovarlo?
>>
>> In generale no.
> 
> K... definitivo!

Il ciclo di vita degli oggetti UNO è ben descritto nella devguide,
http://doc.services.openoffice.org/wiki/Documentation/DevGuide/ProUNO/Lifetime_of_UNO_objects


ma semplificando, il bridge, che è l'elemento che collega il linguaggio
di programmazione (es il Basic) all'API di ooo,

http://doc.services.openoffice.org/wiki/Documentation/DevGuide/AdvUNO/Language_Bindings


deve occuparsi di tenere aggiornato il refcount, ovvero di tener conto
dei riferimenti che puntano ad un dato oggetto (grossolanamente - dal
tuo punto di vista si tratta  delle variabili oggetto)

http://doc.services.openoffice.org/wiki/Documentation/DevGuide/WritingUNO/XInterface
http://api.openoffice.org/docs/common/ref/com/sun/star/uno/XInterface.html

Più o meno succede questo:
quando assegni un oggetto ad una variabile il refcount di quell'oggetto
viene incrementato di 1
Quando rimuovi l'assegnazione, ad esempio assegnando qualcos'altro alla
stessa variabile, il refcount viene decrementato di 1.
Quando il conto arriva a zero vuol dire che non c'è più nessuna
variabile che punta ad un dato oggetto e l'oggetto può essere distrutto.

Nel caso di starbasic pertanto è il bridge che si occupa di fare piazza
pulita degli oggetti "vaganti".
Tecnicamente questa operazione si chiama "garbage collection"

Tratto da wikipedia.it:
[garbage collection]
[....]
Questo meccanismo porta ad un notevole cambio nello stile di
programmazione dei linguaggi che lo implementano. Infatti non è più
possibile richiedere esplicitamente di liberare la memoria utilizzata da
un oggetto, ovvero terminare tale oggetto in modo deterministico, ma si
lascia che il sistema esegua questa operazione automaticamente, nel
momento in cui lo riterrà più opportuno per migliorare le prestazioni
complessive (finalizzazione non deterministica).
[....]





> 
> 
>>> Ma gli oggetti status indicator creabili sono più di uno...
>>
>> Se ne devi creare più di uno devi gestire il codice in modo opportuno
>> Usa più variabili oppure usa un array.
>> La domanda però è: perchè usarne più di uno?
>> Hai più processi che girano in parallelo e devono mostrare il
>> progresso all'utente? Non è così semplice creare architetture del
>> genere in Basic e comunque sarebbe da evitare visto che il basic non
>> ha gli strumenti per gestire task paralleli.
> 
> Ecco... qui tocchiamo uno dei miei problemi... non è che io li voglia
> avviare deliberatamente.
> Alle volte il codice è lento ad eseguirsi... e succede che l'utente avvi
> nel frattempo qualcos'altro.
> Succede per esempio in apertura di un doc... dove in Ultimus deve
> eseguire parecchie cose... io i controlli li blocco... ma se l'utente
> dal file manager clicca su un altro doc.odt è un disatro.
> Questo comunque è un altro problema... ma volevo giustificarmi.

Ok, prendiamo atto che l'architettura della tua app non è deterministica
riguardo all'ordine di esecuzione dei task ed è possibile avere più task
in parallelo.
Come ho già detto questo è un gran casino in basic perchè non hai molti
strumenti per gestire la situazione.

A questo punto per me l'approccio funzionale centralizzato non è adatto,
a meno che tu non voglia gestire le varie istanze in un array o cose
simili, ma sarebbe tutto codice e complessità in più.

La soluzione è quella di usare il servizio nel modo più semplice
possibile, ovvero ogni task si crea la propria istanza di
StatusIndicator, lancia il metodo start quando serve, durante
l'esecuzione dovrà chiamare il metodo setValue o setText e alla fine
provvederà a far sparire la propria istanza con il metodo end()

Qualora ci fossero temporaneamente più task in parallelo, la barra di
stato verrà negoziata tra i vari statusindicator senza aggiungere codice
dedicato.

L'effetto estetico sarà talvolta imprevedibile, ma per il resto dovrebbe
funzionare.

Non ti devi preoccupare di liberare la memoria occupata dalle varie
istanze, il perchè lo abbiamo già detto sopra.


[....]
>> Accidenti ma un occhiatina alla documentazione proprio no?
>> vabè, controllo io: 
[...]
>> A quanto sembra il metodo end() non distrugge l'oggetto. 
> 
> L'avevo intuito... ma non trovo tra i metodi qualcosa in grado di
> distruggerla...

infatti non ce ne sono! viene fatto automaticamente se e quando serve.



> Sull'opportunità di distruggerla possiamo discuterne... ma comunque
> (accademicamente) consentimi la domanda:
> si può fare?
> e se si, come?

Ci sono componenti UNO che danno questa possibilità attraverso il metodo
dispose() altri componenti più semplici come lo statusindicator in
questione non offre questa possibilità. Per la trattazione tecnica del
ciclo di vita degli oggetti UNO ti rimando sempre al capitolo della devguide



> 
> 
>>>> Usa la funzione IsNull() per controllare se la variabile oggetto
>>>> contiene
>>>> già un riferimento valido.
>>> Pare non funzionare... vedi sotto...
>>
>> Funziona.
> 
> .. ?  ....
> 
> 
>>> Global oPG2 as object
>>>
>>> Sub Main_1
>>>     xray oPG2
>>> if isNull (oPG2) then
>>>     print "null"
>>>     oPG2 = ThisComponent.CurrentController.Frame.CreateStatusIndicator
>>>     oPG2.Start("",100)'
>>>     oPG2.Value = 100
>>>     oPG2.Text = "Attendi pazientemente!"
>>>   else
>>>     print "Not null"
>>>     oPG2.end
>>> end if
>>> End sub
>>>
>>> noi creiamo l'oggetto ed una variabile che punta a quell'oggetto.
>>
>> Il codice è tecnicamente corretto ma non ha molto senso.
>> Non si usa così il servizio status-indicator.
> 
> Ecco... ho rigirato il codice sopra in tutti modi che mi venivano in
> mente... ma non ho risolto.

Eliminalo del tutto e usa l'approccio che ti ho suggerito sopra.


> 
> Dove sto sbagliando?
> 
> Come andrebbe scritto il codice?


In generale questo problema si affronta così:

global coso

sub inizializza_coso()

  If IsNull(coso) Then
    coso = CreateUnoService("bim.bum.bam.coso")
  End If

  ' da qui in poi sono sicuro che coso esiste
  ' e posso iniziare ad usarlo
  ...
  ...
  ...
End Sub




> 
>>> Alla seconda esecuzione xray su oPG2 ci visualizza il "contenuto" della
>>> var oPG2, che risulta essere un qualcosa ( no name )
>>
>> Non tutti i servizi UNO hanno un implementation-name
>> In particolare, servizi creati "al volo" come questo, spesso non ce
>> l'hanno
> 
> k ... definitivo.. allora... questo sevizio non ha un nome!

bisognerebbe distinguere tra implementation-name e service-name ma
comunque sia, si, questo servizio non ha nome e non è nemmeno un caso
isolato.


>  > Oppure si può cliccare su "interfaces" in alto a sx nel dialogo di
> XRay per
>> consultare la lista delle interfacce supportate
> 
> si certo... ma sapere che supporta l'interfaccia
> com.sun.star.task.XStatusIndicator continua ad essere un qualcosa di
> generico...

Volevo solo farti notare che c'era una procedura più semplice ma
equivalente a quella che avevi descritto

..e comunque conoscere le interfacce supportate da un oggetto non è
assolutamente "qualcosa di generico" ma anzi, equivale a sapere
esattamente cosa può o non può fare quell' oggetto



>>> ...zot...
>>> e la progressBar sparisce dalla riga di status, e ci si aspetta che
>>> quell'oggetto non esista più.
>>
>> Cioè se un oggetto non si vede non esiste più ?
> 
> Messa in questo modo inevitabilmente NO: l'oggetto continua ad esistere
> 
> Ma a questo punto sarebbe necessario poterlo "mostrare" nella riga di
> status, oppure "NON mostrarlo".
> E per poterlo fare dovremmo sapere il suo "stato" di visibilità.

Siccome sei solo tu con il tuo codice che puoi determinare questo stato,
non c'è bisogno che l'oggetto te ne informi.




>>> Ma nessuno finora ha informato la var oPG2 che l'oggetto sia stato
>>> "terminato"...
>> 1)l'oggetto non è affatto terminato
> 
> k... ormai questo mi è strachiaro... :-)
> 
>> 2) Come si fa ad informare una variabile di qualcosa?
> 
> se si tratta di una variabile stringa direi qualcosa del tipo:
> 
> sVAR = "Tu hai il morbillo"
> 
> ma se cambiamo tipo di variabile la cosa mi sfugge un po'...
> oVar = NULL non credo funzioni...

Invece funziona. :-)
A quanto so non è mai stato documentato ufficialmente, ma io lo uso da anni.
Anche Nothing funziona allo stesso modo

Si tratta di costanti basic, (come True o False) entrambe restituiscono
un valore Null.

Non è un invito ad usare roba non documentata, puoi tranquillamente
usare una variabile object non assegnata in quanto contiene il valore Null:

Dim myNullObj As Object


> 
[...]
> Non vorrei complicare il tutto... ma a me sembra che avere qualcosa li
> appeso (non so dove) mentre apro diversi doc sul mio desktop non sia una
> buona cosa.
> Non sarebbe meglio terminare distruggere il mio oggetto?

Puoi assegnare un valore Null alla variabile che punta al tuo oggetto.
La garbage collection del basic farà il resto.
Ribadisco comunque che per me è sbagliato mettere pezze alla routine
quando sarebbe meglio cambiare completamente approccio.

> 
> (devo parlare al mio analista di questa mia pulsione alla distruzione?)

temo di si :-)
(scherzo)

> 
>> Le variabili non si possono informare. Tu puoi controllare se una
>> variabile oggetto contiene un riferimento ad un oggetto con la
>> funzione IsNull()
> 
> mmm... si, ma la mia variabile, una volta che è stata "riempita" con il
> riferimento all'oggetto, sembra giustamente mantenere il riferimento.

Come sopra: mettici Null oppure una variabile oggetto non assegnata.

> 
> Ma a questo punto, se l'oggetto viene solo reso invisibile,
> interrogare la variabile mi sembra poco utile... perché isNull ci dice
> solo che l'oggetto esiste, e non il suo stato di visibilità.

Come sopra:
Siccome sei solo tu con il tuo codice che puoi determinare i cambiamenti
di stato nel tuo oggetto non c'è bisogno che l'oggetto ti informi dei
suoi cambiamenti di stato.
Al limite dovrebbe essere il tuo codice che quando cambia lo stato dello
statusindicator si preoccupa di settare dei flags pubblici per informare
le altre parti del programma, ma come ho detto si tratta secondo me di
un approccio inutilmente complicato e probabilmente inefficace.

Mi spiego:
Se hai più processi e ti trovi nella situazione in cui la mano destra
non sa quello che fa la sinistra allora non ha più senso usare una sola
istanza dello statusindicator, ma soprattutto non ha senso usare una sub
centralizzata per la sua gestione.
Usa la tecnica che ho esposto più sopra di creare e "consumare"
localmente le istanze degli StatusIndicator.


> E, nel caso non si sia in grado (o non si voglia) distruggere l'oggetto,
>  mi pare che conoscere il suo "stato" di visibilità sia la cosa
> veramente importante.

Non si è in grado di distruggere l'oggetto esplicitamente per i motivi
già esposti.

> 
> (Su quanto sopra sono certo che hai delle idee precise...)
>> eh no! io la pazienza ce la metto, però a questo punto un paio di
>> cosette le devo dire :-)
>> 1) hai iniziato il thread dicendo (più o meno):
>> "Ho questo codice che è corretto, ma nel contesto del mio programma
>> non funziona"
>>
>> Ma io dico: hai un problema nel tuo programma e alleghi l'unica parte
>> di codice che funziona??? 
> 
> :-)
> 
> Paolo... sono 46 moduli... e quasi tutti superano le 1500 linee..
> Ho cercato di postare il nocciolo del problema...
> Un po' di decenza mi è rimasta... :-)

Lo immaginavo, ma quando posti dovresti cercare di isolare il problema
dalla massa del codice.
E' un buon modo per capire cosa succede e ovviamente per farlo capire
agli altri.

> 
>> 2) sei partito dall'assunto che il metodo end() terminasse l'oggetto
>> quando la documentazione dice esattamente il contrario
> 
> Da qualche parte un qualche errore ci doveva pur essere... altrimenti
> non avrei chiesto aiuto! :-)


L'errore che io rilevo è quello di fare la domanda e suggerire anche la
risposta.
Se non sei sicuro rischi di fuorviare l'interlocutore.


>> 4) sulla base di queste hai modificato il pezzo di codice che
>> funzionava rendendolo inservibile.
> 
> Quale era il codice che funzionava?
> la domanda non è polemica... ma tecnica e specifica!

Diciamo che il tuo primo codice era impostato male (secondo me) ma
tecnicamente funzionava.

Il buon funzionamento qui non è riferito al raggiungimento degli scopi
della tua app, ma solo al comportamento del metodo end(), che all'inizio
 era stato usato correttamente.




> 
>> 5) con il codice rappezzato che ovviamente non funziona, ora poni
>> tutta un'altra serie di domande sul perchè non funziona
>> ....
> Paolo... tutto il mio codice è rappezzato!

Quello che con la mia simpatica verve volevo sottolineare è che ci siamo
concentrati su una routine modificandola in modi anche impropri,
perdendo di vista il fatto che il problema non era li ma nel contesto
del tuo programma.



>> Siamo partiti dallo statusindicator e siamo andati a toccare i tipi di
>> variabile, persistenza, visibilità, garbage collector, tutta roba che
>> c'entra poco o nulla e comunque meriterebbe delle discussioni a parte.
> 
> Vero... si... e se continui a maltrattarmi apro 4 nuovi thread in merito...

No dai, se pensi che mi comporti in modo maltrattevole allora mi ritiro
subito! :-)
Il mio tono voleva essere ironico ma volevo anche spiegare il perchè
qualche volta sono un po riluttante ad entrare nei thread.
Sul garbage ho detto qualcosina in questo post che spero sia utile.



> 
>> Ripeto, io la pazienza ce la metto tutta, in fin dei conti a me fa
>> piacere chiacchierare di macro e starbasic, però non riesco a starti
>> dietro!
> 
> Invece ci riesci benissimo... :-)
> e sono certo che 20 righe di codice "buono" sarebbero risolutive!

Ci ragiono e se riesco a mettere insieme qualcosa di adatto alla
situazione lo posto volentieri, però sarebbe d'aiuto capire quali sono
le routine che vanno in "concorrenza" e che hanno bisogno di mostrare il
progresso.

Secondo me la complessità di questo problema non è tanto quella di
mostrare l'uso del servizio ma quella di adattarlo alla tua situazione.


ciao
Paolo M


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Rispondere a