2013-05-09 2 views
4

저는 wxPython과 함께 Python을 사용하여 응용 프로그램을 작성하고 있습니다.유휴 스레드/신호 스레드 설정하기

이 방법을 사용하는 것이 가장 좋지 않을 수 있습니다. 그렇다면 리팩토링에 대해 알고 있기 때문에 알려주세요.

지금은 하나의 GUI 양식이 있습니다. 메인 프로그램 시작 지점은 GUI 양식의 인스턴스를 인스턴스화 한 다음 wx.mainLoop()을 실행하여 앱의 기본 초기 스레드를 앱의 수명 동안 차단합니다.

UI에서 이벤트가 발생하면 UI 스레드가 해당 코드를 실행한다는 것을 알 수 있습니다.

이제는 다른 스레드 인 작업자 스레드가 있습니다. 이 스레드는 유휴 상태에 있어야하며 UI 스레드에서 어떤 일이 발생하면 예를 들어 버튼을 클릭하면 작업자 스레드가 유휴 상태를 멈추고 다른 작업을 수행하기를 원합니다.

저는 지금 당장은 상상할 수 없지만, 실제로 작업 중일 때 작업자 스레드에 신호를 보내야한다는 점에서 앱이 더욱 복잡해지면서 볼 수있었습니다.

나는이 설정에 대한 두 가지 질문이 있습니다

  1. 가 어떻게 CPU 시간을 사용하지 않고 내 작업자 스레드 대기를 할 수 있습니까? while True: pass과 같이하면 while True: time.sleep(0.1)과 같은 이벤트는 이벤트에 대한 즉각적인 반응을 허용하지 않습니다.

  2. 작업자 스레드에 신호를 보내는 가장 좋은 방법은 무엇입니까? UI 스레드가 뭔가를 실행하는 것을 원하지 않습니다. UI 스레드가 작업자 스레드의 신호를 보내고 UI 스레드가 수행중인 작업을 변경해야합니다. 이상적으로는, 작업자 스레드가 UI 자체에 콜백을 등록 할 수있는 방법이 있습니다. 버튼을 클릭하거나 다른 UI 이벤트가 발생하면 작업자 스레드가 신호를 보내 자신이하는 일을 바꿀 수 있습니다.

그래서 이것을 수행하는 가장 좋은 방법입니까? 그리고 그것을하는 가장 좋은 방법은 무엇입니까?

감사합니다.

답변

5

첫 번째 : 처음에는 유휴 상태에 앉아 배경 스레드가 실제로 필요합니까?

대부분의 플랫폼에서 새 스레드를 시작하는 것은 저렴합니다. (Windows 및 Linux를 제외하고는 슈퍼 치입니다.) 그래서 필요할 때마다 스레드를 시작하지 않는 이유는 무엇입니까? (스레드 목록을 단일 스레드로 유지하는 것만 큼 쉽습니다.)

ThreadPoolExecutor을 작성하고 작업을 제출하고 실행할 때 걱정할 필요가없는 이유는 무엇입니까? 및 스레드. "작업을 기다려야하는 작업자 스레드"대신 "주 스레드를 차단하지 않고 실행해야하는 작업"이라는 측면에서 생각하면 언제든지 작업을 쉽게 수행 할 수 있습니다. 커버 아래에는 하나 이상의 작업자 스레드가 대기열에서 대기 중이거나 그와 동등한 작업을 수행하지만 그 부분은 모두 작성되고 디버깅되고 최적화되었습니다. 당신이 작성해야하는 것은 단지 정규 기능인 작업입니다.

그러나 명시 적 배경 스레드를 쓰고 싶다면 그렇게 설명 할 수 있습니다.


가 어떻게 CPU 시간을 사용하지 않고 내 작업자 스레드 대기를 할 수 있습니까? ... 작업자 스레드에 신호를 보내는 가장 좋은 방법은 무엇입니까?

값이 준비 될 때까지 스레드를 유휴 상태로 유지하는 방법은 동기화 개체를 기다리는 것입니다. 최신 OS에서 동기화 객체를 기다리면 해당 객체가 준비 될 때까지 CPU 시간을 제공하지 않습니다. *

Threading 모듈 문서에는 다양한 옵션이 있지만 이처럼 대부분의 경우에 사용되는 분명한 것은 Condition입니다. 작업자 스레드에 신호를 보내는 방법은 notifyCondition입니다.

그러나 종종 Queue은 훨씬 간단합니다. Queue에서 대기하려면 get 메서드를 block=True으로 호출하면됩니다. 깨어나는 다른 스레드에 신호를 보내려면 Queue에있는 put을 입력하십시오. (커버 아래에있는 Queuelist 또는 deque 또는 다른 컬렉션 인 LockCondition을 감싸며, 원하는 것을 말하면됩니다. 값을 확인하고, 값이 될 때까지 차단하고, 값이있을 때까지 차단하고, 대기 및 시그널링을 처리하고 컬렉션을 보호하는 대신).

작업자 스레드에서 UI 스레드로 또는 그 반대로 양방향으로 신호를 보내는 방법은 controlling UI elements in wxPython using threading의 해답을 참조하십시오.


버튼을 클릭하거나 다른 UI 이벤트가 발생했을 때, 작업자 스레드가 무엇을 변경하라는 지시를 내 렸습니다되도록 내가 UI를 자체 콜백을 등록하는 작업자 스레드에 대한 몇 가지 방법이있을 것이다

그것은하고있다.

원하는 경우이 방법을 사용할 수 있습니다. self.queue.put 또는 def callback(value): self.value = value; self.condition.notify() 또는 콜백으로 전달하십시오. GUI 스레드는 콜백이 다른 스레드를 트리거하고 있음을 알 필요조차 없습니다.

사실 인라인과 백그라운드 스레드간에 앞뒤로 코드를 이동하거나 백그라운드 스레드 대신 자식 프로세스로 이동하기로 결정할 때 매우 행복한 디자인입니다. , 또는 무엇이든.


지금이 권리를 상상할 수 없지만 응용 프로그램은이 일을 실제로 바쁜 동안 작업자 스레드를 신호 할 필요도 더 복잡한을수록 나는 볼 수 있었다.

하지만 바쁠 때는 어떻게되고 싶습니까?

"유휴 상태 일 때 일어나서이 작업을 수행하고, 그렇지 않으면 준비하고 언제든지 수행하십시오"라고 말하면 정확히 Queue 또는 Executor입니다. 당신을 위해 자동으로하십시오.

"유휴 상태라면 깨우십시오. 그렇지 않으면 걱정하지 마십시오."즉 Condition 또는 Event이됩니다.

"유휴 상태라면 깨우고 해보십시오. 그렇지 않으면 지금하고있는 일을 취소하고 대신 수행하십시오."라는 말은 조금 더 복잡합니다. 바쁜 동안에 백그라운드 스레드가 주기적으로 "interrupt_me"변수를 확인하고 그 주위에 Lock을 넣을 필요가 있습니다. 그런 다음 해당 플래그를 설정하고 Condition을 알리는 것입니다 ... 경우에 따라 유휴 상태 및 통화 중 상태를 단일 작업으로 병합 (유휴 상태 일 경우 무한 wait()을 호출하고 통화 중일 때는 wait(timeout=0)을 사용) 단일 Condition 또는 Event으로 병합합니다. 일부에서


* 경우 - 예 :., 그 좋은 최적화 될 일이 있기 때문에 실제로, 어떤 경우에는 CPU 시간의 조금을 분사 할 수있다 - 그것은 리눅스 futex 또는 Windows CriticalSection. 그러나 요점은, 당신은 이 아니며, 당신이 그것을 사용할 준비가 될 때까지 어떤 CPU 시간이든을 묻는 것입니다.

+1

"나는 마지막으로 생각해야 할 부분 : ..."섹션을 좋아합니다. –

+0

@PreludeAndFugue : 내가 더 가깝게 이동해야합니까? 나는 이것이 실제로 문제를 해결하는 방법이라고 확신한다. (그의 실제 배경 작업이 무엇인지 알지 못하더라도, "꽤 확실하다"). 그러나 그가 직접 물어 본 것은 아닙니다. – abarnert

+0

예, 그렇게 생각합니다. –

관련 문제