Durante l'utilizzo di un toolkit widget, è importante comprendere il modello di thread sottostante utilizzato per la lettura e la distribuzione degli eventi della GUI della piattaforma. L'implementazione del thread UI influisce sulle regole che le applicazioni devono seguire nell'utilizzo di thread Java nel codice.
Al di sotto di ogni applicazione GUI, indipendentemente dalla lingua o dal toolkit UI in uso, la piattaforma del sistema operativo rileva gli eventi della GUI e li colloca nelle code di eventi dell'applicazione. Sebbene i meccanismi differiscano leggermente a seconda della piattaforma del sistema operativo, i principi di base sono identici. Non appena l'utente fa clic con il mouse, digita caratteri o visualizza finestre, la piattaforma genera gli eventi GUI dell'applicazione, quali i clic del mouse, la selezione di tasti o gli eventi di aggiornamento di una finestra e determina la finestra e l'applicazione che devono ricevere ciascun evento, inserendolo nella coda degli eventi dell'applicazione.
La struttura sottostante a ogni applicazione GUI con finestre costituisce un ciclo di eventi. Una volta inizializzate, le applicazioni avviano un ciclo che legge semplicemente gli eventi della GUI dalla coda e reagisce di conseguenza. Perché il sistema GUI continui a interagire con l'utente, è necessario operare con rapidità durante la gestione di uno di questi eventi.
Le lunghe operazioni attivate dagli eventi UI devono essere eseguite in un thread separato in modo che il thread del ciclo di eventi possa chiudersi rapidamente e recuperare il successivo evento della coda dell'applicazione. Tuttavia, l'accesso ai widget e all'API della piattaforma da altri thread deve essere controllato applicando un blocco e una serializzazione. Un'applicazione che non segue le regole, può generare chiamate al sistema operativo non riuscite o, peggio, il blocco dell'intero sistema GUI.
I programmatori delle GUI native che utilizzano il linguaggio C sono a conoscenza dei problemi di progettazione relativi all'utilizzo del ciclo di eventi della piattaforma. I toolkit widget di livello superiore in Java tentano spesso di limitare i problemi di threading dell'interfaccia utente che gli sviluppatori devono affrontare nascondendo il ciclo di eventi della piattaforma.
Generalmente per raggiungere questo obiettivo, viene impostato un thread UI di toolkit dedicato alla lettura e alla distribuzione dal ciclo di eventi e all'invio degli eventi a una coda interna servita da applicazioni eseguite in thread separati. In questo modo il toolkit può rispondere in tempo al sistema operativo, senza imporre all'applicazione alcuna restrizione di tempo per la gestione dell'evento. Le applicazioni devono ancora utilizzare speciali tecniche di blocco per accedere al codice UI dal loro thread ma, poiché tutto il codice dell'applicazione è in esecuzione in un thread non appartenente all'interfaccia utente, l'operazione avviene in maniera coerente in tutto il codice.
Per quanto possa sembrare interessante "limitare" i problemi relativi al thread UI per le applicazioni, l'operazione nella pratica si rivela molto problematica.
Il debug e la diagnosi dei problemi diventano difficili quando i tempi di esecuzione degli eventi GUI dipende dall'implementazione del threading Java e dalle prestazioni dell'applicazione.
Le moderne piattaforme GUI effettuano molte ottimizzazioni con la coda di eventi. Un processo comune consiste nel comprimere gli eventi di disegno consecutivi nella coda. Ogni volta che è necessario aggiornare parte di una finestra, è possibile controllare nella coda gli eventi di disegno ridondanti o sovrapposti non ancora distribuiti. Tali eventi possono essere riuniti in un unico evento di disegno, in modo da provocare un minore sfarfallio e un'esecuzione meno frequente del codice di disegno dell'applicazione. Questa ottimizzazione risulta superflua se il toolkit widget estrae rapidamente gli eventi dalla coda e li distribuisce a una coda interna.
Una diversa percezione del modello di threading da parte dello sviluppatore può generare confusione per i programmatori esperti nella programmazione del sistema GUI nativo in altri linguaggi e toolkit.
SWT segue il modello di threading supportato direttamente dalle piattaforme. L'applicazione esegue il ciclo di eventi nel thread principale e distribuisce gli eventi direttamente da tale thread, che rappresenta il "thread dell'interfaccia utente" dell'applicazione.
Nota: tecnicamente il thread dell'interfaccia utente crea la classe Display. In pratica, questo thread esegue anche il ciclo di eventi e crea il widget.
Poiché tutto il codice di eventi viene avviato dal thread dell'interfaccia utente dell'applicazione, il codice che gestisce gli eventi può accedere liberamente ai widget per eseguire chiamate grafiche senza richiedere tecniche speciali. Tuttavia, l'applicazione è responsabile della duplicazione dei thread di calcolo durante l'esecuzione di lunghe operazioni in risposta a un evento.
Nota: SWT attiva una SWTException per tutte le chiamate effettuate da un thread non UI che devono essere eseguite dal thread dell'interfaccia utente.
Il thread principale per un'applicazione SWT, incluso il ciclo di eventi, ha il seguente formato:
public static void main(String[] args) { Display display = new Display (); Shell shell = new Shell (display); shell.open (); // avviare il ciclo di eventi. Si verificherà un'interruzione quando l'utente avrà eseguito // un'operazione per eliminare la finestra. while (!shell.isDisposed ()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose (); }
Dopo aver creato i widget e aperto la shell, l'applicazione legge e distribuisce gli eventi dalla coda del sistema operativo fino all'eliminazione della finestra shell. In assenza di eventi disponibili nella coda, la visualizzazione deve rimanere inattiva in maniera che le altre applicazioni possano essere eseguite.
Nota: il modello di threading più comune per un'applicazione SWT prevede l'esecuzione di un singolo thread dell'interfaccia utente e lunghe operazioni in thread di calcolo. Gli sviluppatori, tuttavia, possono anche non attenersi a questo modello. Un'applicazione può eseguire più thread dell'interfaccia utente, ciascuno dei quali dotato di un proprio ciclo di eventi.
SWT fornisce metodi di accesso speciali per chiamare widget e codice grafico da un thread di sfondo.
Le applicazioni che desiderano richiamare un codice UI da un thread non UI devono fornire un eseguibile che richiami il codice UI. Per eseguire questi eseguibili al momento opportuno nel thread dell'interfaccia utente, vengono utilizzati i metodi syncExec(Runnable) e asyncExec(Runnable) nella classe Display.
Il seguente frammento di codice illustra il modello per l'utilizzo di questi metodi:
// eseguire calcoli impegnativi ... // aggiornare ora la UI. Poiché non è necessario attendere il risultato, // usare async. Display.getDefault ().asyncExec (new Runnable () { public void run () { myWindow.redraw(); } }); // eseguire adesso altri calcoli ...
Le regole di threading sono molto chiare quando si esegue una nuova implementazione di un'applicazione SWT, in quanto è possibile controllare la creazione del ciclo di eventi e la decisione di duplicare i thread di calcolo nell'applicazione.
Se si fornisce il codice del plug-in al workbench, nel codice JFace o nel codice del workbench non è nascosto alcun aspetto del threading. Le regole sono lineari: