Ik ben aan de slag gegaan met SWT om een user interface te bouwen. Omdat er stukken code uitgevoerd worden die lang duren (indexeren van documenten mbv Lucene) wilde ik de boel multithreaden. Als je alles in een enkele thread houdt kun je namelijk je GUI niet fatsoenlijk updaten en lijkt hij te bevriezen tijdens indexeer acties.
Dit heb ik nu als volgt opgelost, maar ik heb een beetje het gevoel dat het een ranzige oplossing is, omdat ik een aantal variabelen final heb moeten maken of naar final variabelen heb gekopieerd. Je kunt niet gewoon uit een andere thread de UI-thread aanroepen overigens, dan gooit SWT een illegal thread access exception naar je hoofd. asyncExec en syncExec stonden in de JavaDocs beschreven als mogelijkheden om vanuit andere threads binnen de UI-thread iets uit te laten voeren.
Het werkt wel, maar is vrij omslachtig, en ik vroeg me af of er betere manieren zijn. Uiteraard moet wel de GUI geupdate worden.
Dit heb ik nu als volgt opgelost, maar ik heb een beetje het gevoel dat het een ranzige oplossing is, omdat ik een aantal variabelen final heb moeten maken of naar final variabelen heb gekopieerd. Je kunt niet gewoon uit een andere thread de UI-thread aanroepen overigens, dan gooit SWT een illegal thread access exception naar je hoofd. asyncExec en syncExec stonden in de JavaDocs beschreven als mogelijkheden om vanuit andere threads binnen de UI-thread iets uit te laten voeren.
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
| private static void indexDirectory(IndexWriter writer, File dir) throws Exception { final File[] files = dir.listFiles(); final ProgressBar pgBar = swtUI.getProgressBar(); final List list = swtUI.getList(); swtUI.shell.getDisplay().syncExec( new Runnable() { public void run() { indexSubdirectories = swtUI.getIndexeerSubdirectoriesButton().getSelection(); } }); swtUI.shell.getDisplay().asyncExec (new Runnable () { public void run () { pgBar.setSelection(0); } }); for(int i = 0; i < files.length; i++) { swtUI.shell.getDisplay().asyncExec (new Runnable () { public void run () { pgBar.setMaximum(files.length); } }); File f = files[i]; if(f.isDirectory() && indexSubdirectories) { indexDirectory(writer,f); list.add("Indexeren van directory "+f.getName()); } else if(f.getName().endsWith(".txt")) { indexTXTFile(writer,f); } else if(f.getName().endsWith(".pdf")) { indexPDFFile(writer,f); } else if(f.getName().endsWith(".html")) { indexHTMLFile(writer,f); } else if(f.getName().endsWith(".xml")) { indexXMLFile(writer,f); } final int j = i; swtUI.shell.getDisplay().asyncExec (new Runnable () { public void run () { pgBar.setSelection(j+1); pgBar.redraw(); list.redraw(); } }); } } |
Het werkt wel, maar is vrij omslachtig, en ik vroeg me af of er betere manieren zijn. Uiteraard moet wel de GUI geupdate worden.
[ Voor 6% gewijzigd door tweakerbee op 20-07-2006 15:18 . Reden: code highlighting aan ]
You can't have everything. Where would you put it?