SWT: Respond to Long Running Tasks

 

Most Swing developers are aware of the fact that Swing (and AWT) operate on a single-threaded model, and any changes that are to happen to the UI, should happen in the event dispatch thread. This is a fairly commonly accepted and understood programming model. The biggest difficulty comes in when you are executing fairly intensive code in the UI thread, and suddenly realize that the application is no longer responding to button presses, split-pane resizing, keystrokes, etc. In addition, in pre-Mustang releases (Java 5 and down), the application even ceases to paint. The commonly accepted solution is for those long running operations to be executed on a background thread, leaving the event dispatch thread open to respond to user interaction, but then asking for a small unit-of-work to be executed *back* on the event dispatch thread, to ensure that any UI updates occur from the correct thread.

Typically this is performed by, in the code running in the background thread, creating a Runnable , object, and supplying it to the SwingUtilities or EventQueue class to be invoked as soon as possible:

 

// Note - EventQueue could also be replaced with 'SwingUtilities' in the example below.
// Code in background thread.
doSomeExpensiveProcessing();
EventQueue.invokeLater(new Runnable() {
 public void run() {
  someLabel.setText("Complete!");
 }
});

 

In addition, when you begin modularizing and breaking apart your code, a certain block of code may not be in a position to truly be aware if it is running on the event dispatch thread. If it is, it may be beneficial to execute the visual update immediately, rather than queueing it for later.

 

// Note - EventQueue could also be replaced with 'SwingUtilities' in the example below.
// Code in background thread.
doSomeExpensiveProcessing();
Runnable r = new Runnable() {
 public void run() {
  someLabel.setText("Complete!");
 }
};
if(EventQueue.isEventDispatchThread()) {
 r.run();
}
else {
 EventQueue.invokeLater(r);
}

 

Finally, if you need to ensure (in this background thread) that the UI was updated appropriately, you can ask Swing to let you wait until it is done invoking the runnable:

 

// Note - EventQueue could also be replaced with 'SwingUtilities' in the example below.
// Code in background thread.
doSomeExpensiveProcessing();
Runnable r = new Runnable() {
 public void run() {
  someLabel.setText("Complete!");
 }
};
if(EventQueue.isEventDispatchThread()) {
 r.run();
}
else {
 try {
  EventQueue.invokeAndWait(r);
 }
 catch(InterruptedException e) { /* handle */ }
 catch(InvocationTargetException e) { /* handle */ }
}

 

I'm not here to talk about Swing however. I'm here to talk about SWT. So why all the subterfuge? Well, the truth is, SWT is *also* essentially a single-threaded UI toolkit (it really does differ, but for the sake of a single display discussion, you can believe me and be happy). It suffers from the same effective problems inherent in Swing as seen above. In fact, most anyone who has done multi-threaded SWT programming, and was somewhat careless or forgetful at sometime, has probably seen this stack trace:

 

org.eclipse.swt.SWTException: Invalid thread access
at org.eclipse.swt.SWT.error(SWT.java:2691)
at org.eclipse.swt.SWT.error(SWT.java:2616)
at org.eclipse.swt.SWT.error(SWT.java:2587)
...

 

SWT does make a point to fail-fast when it comes to threading problems; so at least the typical problems don't go unnoticed until production. The question is, however, what do you do if you need to update a label/button/super-duper-control in SWT from a background thread? Well, it's surprisingly similar to Swing:

 

// Code in background thread.
doSomeExpensiveProcessing();
Display.getDefault().asyncExec(new Runnable() {
 public void run() {
  someSwtLabel.setText("Complete!");
 }
});

 

Note that Display objects are keyed by the thread they belong to - in a single display environment (most applications), you don't have to explicitly worry about dispatching your runnable to the *right* display object (the call to getDefault() ) will simply be correct. That being said, it is good to be aware of this detail.

You may notice, however, that there is no is...Thread method on the Display class to match our EventQueue.isEventDispatchThread() method. Thankfully there are plenty of ways to check this - here are a few:

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

 

boolean isDisplayThread1 = Display.getCurrent() != null; // current will be null if current thread doesn't belong to a display object
boolean isDisplayThread2 = Display.findDisplay(Thread.currentThread()) != null; // effectively the same as the call above.
boolean isDisplayThread3 = Display.getDefault().getThread() != Thread.currentThread(); // match the current thread with the default display thread.

 

There are more than likely other ways to do this, but as you can see, it isn't particularly complicated - each of these solutions is based in the world of checking the current thread, and seeing if there is a display object registered for it.

 

// Code in background thread.
doSomeExpensiveProcessing();
Runnable r = new Runnable() {
 public void run() {
  someSwtLabel.setText("Complete!");
 }
};
 
if(Display.getCurrent() != null) {
	r.run();
}
else {
	Display.getDefault().asyncExec(r);
}

 

Finally, the display class also supports synchronous execution:

 

// Code in background thread.
doSomeExpensiveProcessing();
Runnable r = new Runnable() {
 public void run() {
  someSwtLabel.setText("Complete!");
 }
};
 
if(Display.getCurrent() != null) {
	r.run();
}
else {
	Display.getDefault().syncExec(r); // notice SYNC exec
}

 

Finally, some things to note:

 

  • the code I show here is not best-of-breed code for your infrastructure, it is simple to demonstrate the features in SWT.
  • Synchronized dispatch ( invokeAndWait and syncExec ) often provide more options for ensuring code executes in the correct order, but also has the negative side effect of opening a world of possibilities for deadlocks. Take care when using these methods across broad infrastructures of code.
  • As opposed to checking the thread that you are currently on to determine if it is best to execute the runnable directly, you *do* have the option of always simply passing the runnable to the dispatch thread in question. This can have an effect on the order of operations, however - by executing it directly, you know it is executing right away - if you queue it up using invokeLater or asyncExect however, it may be third, fourth, fifth, or seventy-ninth in line, and you have no guarantee of ordering.

 

Until next time,

R.J. Lorimer

 

 

[출처] http://www.javalobby.org/java/forums/t43753.html

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
184 jsoup을 활용해서 Java에서 HTML 파싱하는 방법 정리 file 졸리운_곰 2017.03.04 157
183 Java Naming conventions 자바 명명 규칙 졸리운_곰 2017.03.04 74
182 NSA의 Dataflow 엔진 Apache NiFi 소개와 설치 file 졸리운_곰 2017.01.23 463
181 wordpress-java-integration 자바와 워드프레스 통합 졸리운_곰 2016.12.30 166
180 XQuery를 이용한 Screen-Scraping file 졸리운_곰 2016.11.29 168
179 Getting Started with Custom Deserialization in Jackson 졸리운_곰 2016.11.18 168
178 how to parse json array value using json node 졸리운_곰 2016.11.17 60
177 How to convert Java object to / from JSON (Jackson) 졸리운_곰 2016.11.16 78
176 Create New Posts in Wordpress using Java and XMLRpc 졸리운_곰 2016.11.14 69
175 자바로 POST 방식으로 통신하기, java httppost 클래스를 활용한 예제 졸리운_곰 2016.11.14 444
174 [Java]아파치 HttpClient사용하기 file 졸리운_곰 2016.11.14 104
173 Timer 클래스를 이용한 작업 스케쥴링 졸리운_곰 2016.11.14 97
172 SQLite Java Tutorial 졸리운_곰 2016.08.11 84
171 numerical analysis with java examples - turhancoban.com.pdf file 졸리운_곰 2016.06.07 263
170 MyBatis 기본 - selectList file 졸리운_곰 2016.06.07 292
169 Mybatis ResultMap 그리고 select 졸리운_곰 2016.06.07 267
168 Mybatis selectList 예제 졸리운_곰 2016.06.05 448
167 java 에서 mybatis 사용한 예제 file 졸리운_곰 2016.06.05 462
166 [Mybatis] 간단한 마이바티스 CRUD 예제 file 졸리운_곰 2016.06.05 273
165 자바 8 살펴보기 file 졸리운_곰 2016.05.23 277
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED