Ho letto un buon blog qualche tempo fa che discute di questo problema (citato da Karl Bielefeldt), quello che sostanzialmente dice è che è molto pericoloso cercare di rendere sicuro il thread del kit UI, poiché introduce possibili deadlock e su come è implementato, le condizioni di gara nel framework.
C'è anche una considerazione prestazionale. Non tanto adesso, ma quando Swing è stato rilasciato per la prima volta, è stato pesantemente criticato per le sue prestazioni (state male), ma non è stata colpa di Swing, è stata la mancanza di conoscenza della gente su come usarlo.
SWT applica il concetto di sicurezza del thread generando eccezioni se lo violano, non grazioso, ma almeno ne sei consapevole.
Se osservi il processo di pittura, ad esempio, l'ordine in cui gli elementi vengono dipinti è molto importante. Non vuoi che il dipinto di un componente abbia un effetto collaterale su qualsiasi altra parte dello schermo. Immagina di poter aggiornare la proprietà di testo di una etichetta, ma è stata dipinta da due thread diversi, potresti finire con un output corrotto. Quindi tutta la verniciatura viene eseguita all'interno di un singolo thread, normalmente basato sull'ordine dei requisiti / richieste (ma a volte condensato per ridurre il numero di cicli di verniciatura fisici effettivi)
Hai menzionato il passaggio da Swing a JavaFX, ma avresti questo problema con qualsiasi framework dell'interfaccia utente (non solo i thick client, ma anche il web), Swing sembra essere quello che evidenzia il problema.
Potresti progettare un livello intermedio (un controller di un controller?) il cui compito è garantire che le chiamate all'interfaccia utente siano sincronizzate correttamente. È impossibile sapere esattamente come progettare le parti non UI dell'API dal punto di vista dell'API dell'interfaccia utente e la maggior parte degli sviluppatori si lamenterebbe che qualsiasi protezione dei thread implementata nell'API dell'interfaccia utente fosse restrittiva o non soddisfacesse le proprie esigenze. Meglio permetterti di decidere come vuoi risolvere questo problema, in base alle tue esigenze
Uno dei maggiori problemi che devi considerare è la capacità di giustificare un determinato ordine di eventi, sulla base di input conosciuti. Ad esempio, se l'utente ridimensiona la finestra, il modello Event Queue garantisce che si verifichi un determinato ordine di eventi, questo potrebbe sembrare semplice, ma se la coda ha consentito agli eventi di essere attivati da altri thread, non è più possibile garantire l'ordine in che gli eventi potrebbero accadere (una condizione di competizione) e all'improvviso devi iniziare a preoccuparti dei diversi stati e non fare una cosa finché non accade qualcos'altro e inizi a dover condividere le bandiere di stato e finisci con gli spaghetti.
Okay, potresti risolvere questo problema avendo una sorta di coda che ordinava gli eventi in base al momento in cui sono stati rilasciati, ma non è quello che abbiamo già? Inoltre, non si può ancora garantire che il thread B possa generare i suoi eventi DOPO il thread A
Il motivo principale per cui le persone si arrabbiano per il fatto di dover pensare al loro codice, è perché sono costretti a pensare al loro codice / design. "Perché non può essere più semplice?" Non può essere più semplice, perché non è un problema semplice.
Ricordo quando è stata rilasciata la PS3 e Sony stava parlando del processore Cell ed è in grado di eseguire linee separate di logiche, decodificare audio, video, caricare e risolvere i dati del modello. Uno sviluppatore di giochi ha chiesto, "È tutto fantastico, ma come sincronizzi i flussi?"
Il problema di cui lo sviluppatore stava parlando era che, a un certo punto, tutti quei flussi separati avrebbero dovuto essere sincronizzati fino alla pipe singola per l'output. Il povero presentatore si limitò a scrollare le spalle in quanto non era un problema a cui erano familiari. Ovviamente, hanno avuto soluzioni per risolvere questo problema ora, ma è divertente al momento.
I computer moderni stanno prendendo molto input da molti luoghi diversi simultaneamente, tutti gli input devono essere elaborati e consegnati all'utente in modo da non interferire con la presentazione di altre informazioni, quindi è un problema complesso , senza una sola soluzione semplice.
Ora, avendo la possibilità di cambiare framework, non è una cosa facile da progettare, BUT, prendi MVC per un momento, MVC può essere multistrato, cioè potresti avere un MVC che tratta direttamente con la gestione dell'interfaccia utente framework, è quindi possibile eseguire il wrapping che, di nuovo, in un MVC di livello superiore che tratta le interazioni con altri framework (potenzialmente multi-thread), sarebbe responsabilità di questo layer determinare come viene informato / aggiornato il layer MVC inferiore.
Utilizzerai quindi la codifica per interfacciare i modelli di progettazione e i modelli di fabbrica o di costruzione per costruire questi diversi livelli. Ciò significa che i framework multithreading vengono disaccoppiati dal livello dell'interfaccia utente tramite l'uso di un livello intermedio, come idea.