위지트(widget) 툴킷을 사용할 경우 플랫폼 GUI 이벤트를 읽고 디스패치하는 데 사용되는 기본 스레드 모델을 이해해고 있어야 합니다. UI 스레드를 구현하면 Java 스레드를 자신의 코드에 사용할 때 응용프로그램에서 준수해야할 규칙에 영향을 미칩니다.
모든 GUI 응용프로그램에서 언어나 UI 툴킷에 상관 없이 OS 플랫폼은 GUI 이벤트를 검색하여 이를 응용프로그램 이벤트 대기열에 배치합니다. OS 플랫폼에 따라 구조는 약간 다르지만 기본은 유사합니다. 사용자가 마우스를 클릭하거나, 문자를 입력하거나, 창의 표면을 스칠 경우 OS에서는 마우스 클릭, 키 입력, 창 페인트 이벤트 같은 응용프로그램 GUI 이벤트를 생성합니다. OS는 이벤트를 받는 창과 응용프로그램을 결정하고 이를 응용프로그램의 이벤트 대기열에 배치합니다.
창으로 된 GUI 응용프로그램의 기본 구조는 이벤트 루프입니다. 응용프로그램을 초기화하고 대기열에서 GUI 이벤트를 읽는 루프를 시작한 다음 적절하게 응답합니다. 이 이벤트를 처리하는 중에 수행하는 모든 작업은 GUI 시스템이 사용자에게 응답할 수 있도록 신속하게 이루어져야 합니다.
UI 이벤트로 트리거된 시간이 오래 걸리는 작업은 별도의 스레드에서 수행해야 합니다. 이벤트 루프 스레드가 빨리 돌아와서 응용프로그램 대기열의 다음 이벤트를 페치하도록 하기 위함입니다. 그러나 다른 스레드에서 위지트(widget)와 플랫폼 API에 액세스하는 것은 잠금과 직렬화로 제어해야 합니다. 응용프로그램에서 규칙을 따르지 못하면 OS 호출이 실패하거나 전체 GUI 시스템이 잠길 수 있습니다.
SWT는 플랫폼에서 직접 지원하는 스레딩 모델을 따릅니다. 응용프로그램은 자신의 기본 스레드에서 이벤트 루프를 실행하고 이 스레드로부터 바로 이벤트를 디스패치합니다. UI 스레드는 Display가 작성된 스레드입니다. 다른 모든 위지트(widget)는 UI 스레드에서 작성해야 합니다.
응용프로그램의 UI 스레드에서 모든 이벤트 코드가 트리거되기 때문에 이벤트를 처리하는 응용프로그램 코드에서는 자유롭게 위지트(widget)에 액세스하고 특별한 기술을 사용하지 않고 그래픽을 호출할 수 있습니다. 그러나 응용프로그램은 이벤트에 응답하여 시간이 오래 걸리는 작업을 수행할 경우 계산 스레드를 분기해야 합니다.
참고: SWT는 UI 스레드로부터 수행해야 하는 비UI 스레드의 호출에 대해 SWTException을 트리거합니다.
SWT 응용프로그램에 대한 이벤트 루프를 포함한 기본 스레드의 구조는 다음과 같습니다.
public static void main (String [] args) { Display display = new Display (); Shell shell = new Shell (display); shell.open (); // start the event loop. We stop when the user has done // something to dispose our window. while (!shell.isDisposed ()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose (); }
위지트(widget)가 만들어지고 쉘이 열리면 응용프로그램은 쉘 창이 삭제될 때까지 OS 대기열에서 이벤트를 읽어 디스패치합니다. 대기열에 사용할 수 있는 이벤트가 없으면 다른 응용프로그램이 실행될 수 있도록 디스플레이가 일시 정지하도록 명령합니다.
SWT에서는 배경 스레드에서 위지트(widget)와 그래픽 코드를 호출하기 위해 특별한 액세스 방법을 제공합니다.
비UI 스레드에서 UI 코드를 호출하려는 응용프로그램은 UI 코드를 호출하는 실행 프로그램을 제공해야 합니다. Display 클래스의 syncExec(Runnable) 및 asyncExec(Runnable) 메소드를 사용하여 이벤트 루프 동안 UI 스레드에서 이 실행 프로그램을 실행합니다.
다음 코드 스니펫에서는 이 메소드를 사용하기 위한 패턴을 설명합니다.
// do time-intensive computations ... // now update the UI. We don't depend on the result, // so use async. display.asyncExec (new Runnable () { public void run() { if (!myWindow.isDisposed()) myWindow.redraw(); } }); // now do more computations ...
asyncExec를 사용할 때 실행 프로그램 내에서 사용자 위지트(widget)가 처리되는지 확인하는 것은
좋은 연습입니다. asyncExec
호출과 실행 프로그램의 실행 사이에
UI 스레드에서 다른 사항이 발생하므로, 실행 프로그램 실행 시 사용자 위지트의 상태를
확신할 수 없습니다.
SWT 응용프로그램을 완전하게 구현할 경우 스레딩 규칙은 매우 명확합니다. 이벤트 루프의 생성과 응용프로그램에서 계산 스레드를 분기하기 위한 결정을 사용자가 제어하기 때문입니다.
플러그인 코드를 Workbench에 제공할 때 조금 더 복잡해 지는 사항이 있습니다. 릴리스 사이에 다음 규칙에 대한 예외는 있지만, 플랫폼 UI 클래스를 사용할 때 다음 규칙을 "시행 규칙"으로 고려할 수 있습니다.