Quando si utilizza un toolkit widget, è importante comprendere il sottostante modello di thread utilizzato per leggere e distribuire eventi GUI di piattaforma. L'implementazione del thread UI influenza le regole che le applicazioni devono seguire nell'utilizzo di thread Java nel codice.
In ogni applicazione GUI, la piattaforma del sistema operativo rileva gli eventi GUI e li inserisce in code di eventi dell'applicazione, indipendentemente dal linguaggio o dal toolkit UI adoperati. 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, selezione di tasti o eventi di aggiornamento di una finestra. La piattaforma determina quale finestra (e applicazione) deve ricevere l'evento e lo inserisce nella coda eventi dell'applicazione.
La struttura sottostante a ogni applicazione GUI con finestre costituisce un ciclo di eventi. Dopo l'inizializzazione, le applicazioni avviano un ciclo che legge semplicemente gli eventi GUI in 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 restituire il prossimo evento dalla coda dell'applicazione. Tuttavia, l'accesso ai widget e all'API di piattaforma da altri thread deve essere controllato applicando un blocco e una serializzazione. Un'applicazione, che non segue le regole, può causare chiamate al sistema operativo non riuscite o, peggio, il blocco dell'intero sistema GUI.
I programmatori della GUI nativa mediante C hanno familiarità con le considerazioni di progettazione relative all'utilizzo del ciclo di eventi della piattaforma. In ogni caso, molti toolkit widget di livello superiore in Java tentano spesso di limitare i problemi di thread UI che gli sviluppatori devono affrontare nascondendo il ciclo di eventi della piattaforma.
Generalmente per raggiungere l'obiettivo, viene impostato un thread UI di toolkit dedicato alla lettura e distribuzione dal ciclo eventi e l'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 più eventi paint nella coda. Ogni volta che è necessario aggiornare parte di una finestra, è possibile eseguire un controllo della coda per gli eventi paint ridondanti o sovrapposti non ancora distribuiti. Tali eventi possono essere riuniti in un unico evento paint, in modo da provocare un minore sfarfallio e un'esecuzione meno frequente del codice paint dell'applicazione. L'ottimizzazione viene vanificata 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 chiamate grafiche senza richiedere tecniche speciali. L'applicazione, comunque, è responsabile della duplicazione di thread di calcolo durante l'esecuzione di lunghe operazioni in risposta a un evento.
Nota: SWT attiva una SWTException per tutte le chiamate fatte 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();
// avvia il ciclo eventi. Esso si interromperà quando l'utente avrà eseguito
// qualche disposizione sulla 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 alla disposizione 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 potrebbe 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 costituisce il modello per l'utilizzo di questi metodi.
// eseguire calcoli lunghi
...
// aggiornare ora la UI. Poiché non è necessario attendere il risultato,
// usare async.
Display.getCurrent().asyncExec(new Runnable() {
public void run() {
myWindow.redraw();
}
});
// eseguire adesso altri calcoli
...
Le regole di threading sono molto chiare nel corso di una nuova implementazione di un'applicazione SWT, perché è possibile controllare la creazione di un ciclo di eventi e la decisione di duplicare i thread di calcolo nell'applicazione.
Per quanto riguarda le regole per fornire il codice plug-in al workbench, non esistealcun aspetto "nascosto" dei threading nel codice del workbench o JFace. Le regole sono lineari.