Fix cross-thread : queue + QTimer polling au lieu de signal

Thread Flask met les photos dans une queue.Queue().
QTimer(500ms) dans le thread principal Qt poll la queue
et appelle le callback. Approche fiable et simple.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-21 22:56:50 +01:00
parent 29cb993b7b
commit defb5d101e

View File

@@ -3,8 +3,9 @@
import os
import threading
import time
import queue
from flask import Flask, request, jsonify, render_template_string
from PyQt6.QtCore import QObject, pyqtSignal
from PyQt6.QtCore import QObject, pyqtSignal, QTimer
UPLOAD_DIR = os.path.join(os.path.dirname(__file__), "..", "..", "data", "photos")
ALLOWED_EXTENSIONS = {"jpg", "jpeg", "png", "bmp", "tiff", "tif", "webp", "heic"}
@@ -280,10 +281,16 @@ class UploadServer:
self.port = port
self.signals = UploadSignals()
self._callback = None
self._queue = queue.Queue()
self.app = Flask(__name__)
self._setup_routes()
self._thread = None
# Timer Qt qui poll la queue depuis le thread principal
self._poll_timer = QTimer()
self._poll_timer.timeout.connect(self._poll_queue)
self._poll_timer.start(500)
os.makedirs(UPLOAD_DIR, exist_ok=True)
def _setup_routes(self):
@@ -309,11 +316,7 @@ class UploadServer:
saved.append(path)
if saved:
# QTimer.singleShot est thread-safe et exécute dans le thread principal
from PyQt6.QtCore import QTimer
from functools import partial
if self._callback:
QTimer.singleShot(0, partial(self._callback, saved))
self._queue.put(saved)
return jsonify({"ok": True, "count": len(saved)})
@@ -321,6 +324,16 @@ class UploadServer:
"""Définit le callback appelé quand des photos sont uploadées."""
self._callback = callback
def _poll_queue(self):
"""Appelé par QTimer dans le thread principal Qt."""
while not self._queue.empty():
try:
photos = self._queue.get_nowait()
if self._callback:
self._callback(photos)
except queue.Empty:
break
def start(self):
"""Démarre le serveur dans un thread daemon."""
self._thread = threading.Thread(