giovedì 14 ottobre 2010

SWT Widget Disposed & asyncExec

Quando si eseguono operazioni time-consuming in una applicazione SWT occorre che queste siano eseguite fuori dal thread grafico, pena il freeze dell'interfaccia grafica. SWT mette a disposizione due metodi per l'esecuzione di task lunghi:
  • i job, simili a dei thread Java contengono il codice da eseguire secondo una politica di schedulazione (anche immediata)
  • gli sync/asyncExec, ossia l'esecuzione di un Runnable appena il thread grafico (UI Thread) può
I due approcci, seppur simili,hanno un utilizzo piuttosto differente: i job vengono usati per tutto quello che è prevalentemente non-UI e che non aggiornerà l'interfaccia grafica, mentre gli xxxExec sono per quei processi che richiedono un aggiornamento costante dell'interfaccia grafica, ad esempio per riportare il progresso di una operazione.
Il problema degli asyncExec è che potrebbero venire schedulati per l'esecuzione dopo il disposal di un widget, cosa che si verifica ad esempio quando l'applicazione viene chiusa. In questo caso viene generata una eccezione SWTException che indica appunto che era rimasto in coda un qualche Runnable per l'esecuzione ma che il thread UI non ha fatto in tempo ad eseguirlo prima della chiusura del widget:
 
org.eclipse.swt.SWTException: Failed to execute runnable (org.eclipse.swt.SWTException: Widget is disposed) 

Per ovviare al problema, ogni asyncExec deve testare la validità del widget sopra il quale opera prima di effettuare le modifiche. Si noti che non basta controllare la validità del widget prima della schedulazione del Runnable, poiché questo problema si verifica in base alla capacità del thread UI di schedulare i Runnable e questa non è nota a priori. I Control dispongono tutti di un metodo isDisposed(), che non è però esposto in un Viewer, perciò se si opera con questi ultimi occorre prima recuperare il Control interno (getControl()) e testare quest'ultimo.





 

Nessun commento: