2012-10-16 1 views
1

약간의 문제가 있습니다. 이제는 작은 Java 프로젝트에서 작업해야합니다. Button 이벤트 핸들러에서 몇 개의 스레드를 실행하려고합니다. 마지막 스레드 중 하나는 UI에서 TextArea를 업데이트해야합니다. 스레드는 전산 작업을하고 있습니다. 가장 중요한 부분은 UI woks를 잘 만드는 것입니다. UI를 고정시키고 싶지 않고 물론 다른 스레드 중 하나에서 UI의 TextArea를 정기적 인 간격으로 업데이트하려고합니다 (UI의 것이 아닌). 버튼의 이벤트 핸들러 내부Java : 일부 비동기 작업을 시작하고 다른 스레드에서 UI를 업데이트하는 방법은 무엇입니까?

내가이 4 개 개의 스레드를 시작 해요 :

Thread generate = new CombinaMaker(); 
generate.run(); 

Thread forward = new TranslateForward(); 
forward.run(); 

Thread backward = new TranslateBackward(); 
backward.run(); 

Thread refresh = new Refresher(); 
refresh.run(); 

내가 스레드가 동시에 작업 할 그래서 여기 내 코드의 일부이다. 리프레셔 스레드는 UI TextArea 구성 요소를 정기적으로 업데이트해야합니다.

public static void updateProgress() 
{ 
    SwingUtilities.invokeLater(new Runnable() 
    { 
     public void run() 
     { 
      //HERE 
      //I have a loop that have to be looping at every 500 ms 
     } 
    } 
} 

내 qustion은 다음과 같습니다 : 그 링크이 일을 하죠 그래서, 여기에

내가 원기를 회복 스레드에서 UI를 업데이트하는 방법입니다? 나는 간단하고 효과적 일 필요가있다. 이 루프는 애플리케이션이 작동하는 한 루핑되어야하므로 슬프다. 이것이 UI를 정지시키는 이유일까요? 나는 어딘가에서 큰 실수를하고 있다는 것을 알고 있지만,이 순간 나는 그것을 혼자 발견 할 수 없다. 나에게 몇 가지 간단한 해결책을 제안 해 주시겠습니까? 그리고 마지막 생각 - 처음 4 개의 스레드 : 나는 UI를 동결하지 않고 '동시에'시작하고 싶습니다. 그런 식으로 (이벤트 처리기에서 이런 식으로 시작하는 ...) 올바른 것일 수도 있고 더 좋을 수도 있습니까? 고마워요. 많은 친구들!

추신. 내 '리프레셔'스레드를 통해 UI 새로 고침이 힘든 경우 타협을위한 준비가되었습니다. - 소유 스레드 (UI 스레드)를 통해 UI를 업데이트하십시오. 그러나이 경우에는 UI의 동결을 피하면서 '시간 촬영 메커니즘'을 사용해야 할 수도 있습니다. 너 무슨 생각해?

+0

특히 코드에 어떤 문제가 있습니까? 다른 스레드 또는 TimerTasks를 사용하는 것은 기본적으로 수행해야하는 작업입니다. –

+0

루프가 업데이트 진행 중 - UI가 멈추는 것을 피하는 방법? 타이머 작업? –

+0

이것은 아마도 끔찍한 충고이지만 뷰 객체에 대한 참조를 다른 스레드로 전달한 다음 해당 스레드가 뷰에 직접 데이터를 추가하도록합니다. 작은 프로그램을 위해 충분히 잘 작동합니다. 내가 제품이나 뭐든지 발표 할 수 있을지 확신하지 못한다. – aglassman

답변

3

주요 문제는 당신의 알고리즘입니다. 대신

SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 
     //HERE 
     //I have a loop that have to be looping at every 500 ms 
    } 
} 

의 당신은해야

// HERE 
// I have a loop that have to be looping at every 500 ms 
// and when something must be updated in the GUI: 
SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 
     // update the GUI as fast as possible 
    } 
}); 

while (true) { 
    Thread.sleep(500L); 
    String update = getUpdate(); 
    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      textArea.append(update); 
     } 
    }); 
} 

실행 가능한 SwingUtilities.invokeLater()는 이벤트 발송 쓰레드 실행에 전달. 장기 실행 태스크를 실행하지 않아야합니다. 끊임없이 반복하는 것은 매우 오래 실행되는 작업입니다.

1

SwingUtilities.invokeLater는 장기 실행 스레드를 호출하도록 설계되지 않았습니다. 문제의 해결책은 this one 일 수 있습니다.

또한 루프와 SwingUtilities.invokeLater 호출의 중첩을 반전을 시도 할 수 있지만, 이것의 가능성은 실행 가능한에서 루프 코드의 나머지 부분에

do { 
    // Sleep and other stuff 
    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
     // Update UI 
     } 
    }); 
} while(...); 
2

원하지 않는 따라 달라집니다 invokeAndDoLater에 전달합니다. 예를 들어 이것을보십시오 : http://www.javamex.com/tutorials/threads/invokelater.shtml

+0

주어진 링크는 성공적으로 OP를 눈 멀게하지만, 런너 블 내부의 루프에 대해서는 아무 것도 말하지 않습니다. ASAIK는 runnable에 루프를 갖는 것이 잘못되어서는 안된다. 이것은 시스템과 관련하여 다른 스레드 일 뿐이다. 유일한 문제는 이벤트 디스패치와 동기식이므로 루프가 종료되거나 yield()되지 않으면 이벤트 디스패치가 차단됩니다. –

+0

많은 스윙 개체는 동기화되지 않으므로 다른 스레드에서 업데이트하지 않는 것이 중요합니다. InvokeAndDoLater의 목적은 AWT 업데이트 스레드에서 변경 사항을 얻는 것입니다 (따라서 AWT 스레드와 경쟁 조건을 피하십시오). UI가 작업이 완료 될 때까지 멈추기 때문에 루프와 같이 해당 스레드에서 많은 작업을 수행하지 않으려 고합니다. 따라서 기술적으로 당신을 막을 수는 없지만 응답 성있는 UI를 원한다면 매우 나쁜 생각입니다. – Gus

1

나는 UI를 동결 싶지 않다위한

엄지 손가락 최대 UI 물론 동결하고 싶지 않아요.불행하게도

내가 정기적으로

에서 다른 스레드 중 하나에서 UI의 텍스트 영역을 업데이트 할 것은 옵션이 아닙니다. Swing 구성 요소 업데이트는 UI 스레드 (Event Dispatch Thread)에서 수행해야합니다. 다행히 스윙은 일정한 간격으로 UI를 업데이트하기위한 내장 클래스 인 javax.swing.Timer 클래스를 가지고있다. Timer은 백그라운드에서 실행되며 Event Dispatch Thread에서 실행되므로이 ​​작업에 가장 적합합니다.

관련 문제