본문 바로가기
코딩취미/Python

파이썬에서 안전하게 스레드 멈추기

by 브링블링 2025. 2. 28.
반응형

PySide6에서 안전하게 스레드 멈추기

 

PySide6에서 UI를 멈추지 않고 백그라운드 작업을 수행하려면 QThread를 활용해야 합니다. 하지만 한 번 실행된 스레드를 안전하게 멈추는 방법을 모른다면 프로그램이 멈추거나 오류가 발생할 수 있습니다. 이 글에서는 QThread를 활용하여 스레드를 실행하고, 안전하게 정지 명령을 전달하여 스레드를 중단하는 방법을 설명합니다. 


1. 스레드란?

🔍 스레드 개념 쉽게 이해하기

컴퓨터 프로그램은 기본적으로 한 가지 작업을 순차적으로 처리합니다. 하지만, 프로그램이 하나의 작업만 처리한다면 시간이 오래 걸리는 연산이 있을 경우 UI가 멈추거나 응답하지 않는 현상이 발생할 수 있습니다.

이를 해결하기 위해 멀티스레딩(Multithreading) 을 사용하면 여러 개의 작업을 동시에 실행할 수 있습니다. 스레드는 하나의 프로그램 내에서 독립적으로 실행되는 작은 단위의 작업을 의미합니다.

🖥️ 스레드의 실생활 예시

  1. 유튜브 동영상 시청: 동영상을 재생하는 동안 UI는 버튼 클릭을 계속 받을 수 있음.
  2. 파일 다운로드: 백그라운드에서 다운로드가 진행되면서 동시에 다른 작업을 수행할 수 있음.
  3. 채팅 프로그램: 메시지를 보내고 받는 동안 UI가 멈추지 않음.

⚠️ 스레드 사용 시 주의할 점

  • 여러 개의 스레드가 동시에 실행되면 충돌이 발생할 수 있음.
  • UI 업데이트는 반드시 메인 스레드에서 실행해야 함.
  • 스레드를 안전하게 종료하지 않으면 프로그램이 비정상적으로 동작할 수 있음.

2. 필요한 사항

PySide6에서 스레드를 활용하려면 아래 사항을 확인하세요.

📌 필요한 모듈

  • PySide6.QtCore 모듈: QThread, Signal, Slot 사용
  • PySide6.QtWidgets 모듈: UI 구성에 필요한 QApplication, QPushButton, QVBoxLayout, QWidget 사용

⚠️ 스레드 관련 주의점

  • UI 업데이트는 반드시 메인 스레드에서 실행해야 합니다.
  • QThreadterminate() 메서드는 사용하지 않는 것이 좋습니다. 강제 종료는 예상치 못한 오류를 유발할 수 있기 때문입니다.
  • QThreadisRunning()을 활용하여 스레드 상태를 체크할 수 있습니다.
반응형

3. 예제 코드

다음 예제에서는 WorkerThread 클래스를 생성하여 백그라운드 작업을 실행하고, 버튼을 눌러 스레드를 멈출 수 있도록 구현합니다.

✏️ 코드 설명

  1. WorkerThread 클래스는 QThread를 상속받아 실행됩니다.
  2. run() 메서드에서 루프를 실행하면서 작업을 수행합니다.
  3. stop() 메서드를 만들어 안전하게 루프를 종료하도록 설정합니다.
  4. UI에서 버튼을 눌러 스레드를 시작하고 중지할 수 있도록 연결합니다.
import sys
import time
from PySide6.QtCore import QThread, Signal
from PySide6.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget

class WorkerThread(QThread):
    progress = Signal(int)  # 진행 상태를 전달하는 시그널
    
    def __init__(self):
        super().__init__()
        self._is_running = True  # 스레드 실행 상태 플래그
    
    def run(self):
        count = 0
        while self._is_running:
            count += 1
            self.progress.emit(count)  # 진행 상태 시그널 전송
            time.sleep(1)  # 1초 대기
    
    def stop(self):
        self._is_running = False  # 스레드 종료 플래그 설정

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
    
    def initUI(self):
        self.setWindowTitle("QThread 정지 예제")
        self.setGeometry(100, 100, 300, 200)
        
        self.button_start = QPushButton("스레드 시작", self)
        self.button_stop = QPushButton("스레드 정지", self)
        
        self.button_start.clicked.connect(self.start_thread)
        self.button_stop.clicked.connect(self.stop_thread)
        
        layout = QVBoxLayout()
        layout.addWidget(self.button_start)
        layout.addWidget(self.button_stop)
        self.setLayout(layout)
        
        self.thread = WorkerThread()
        self.thread.progress.connect(self.update_status)
    
    def start_thread(self):
        if not self.thread.isRunning():
            self.thread = WorkerThread()
            self.thread.progress.connect(self.update_status)
            self.thread.start()
    
    def stop_thread(self):
        self.thread.stop()
        self.thread.wait()  # 스레드가 완전히 종료될 때까지 대기
    
    def update_status(self, count):
        print(f"진행 상태: {count}")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

4. 테이블 정리

항목 설명
QThread PySide6에서 스레드를 실행하는 클래스
run() 스레드 실행 시 호출되는 메서드 (여기에 반복 작업 작성)
stop() 스레드 종료 플래그를 변경하는 메서드
progress 작업 진행 상태를 시그널로 전달
isRunning() 스레드가 실행 중인지 확인하는 메서드
wait() 스레드 종료를 대기하는 메서드
 
반응형