: ic$dZddlZddlmZmZddlmZmZmZej e Z GddeZ Gdde Z Gd d e Zdd ededefdZd ddedefdZdS)a' Cancelable Thread Base Classes ================================ Thread sicuri con supporto per cancellazione graceful. Sostituisce l'uso pericoloso di QThread.terminate(). Features: - Cancellazione graceful con flag - Timeout configurabile - Pulizia automatica risorse - Signal standardizzati N)QThread pyqtSignal)CallableAnyDictceZdZdZeeZeZfdZe de fdZ dZ de fdZdefdZd Zd ZxZS) CancelableThreada@ Base class per thread che supportano cancellazione graceful. Usage: class MyDataLoader(CancelableThread): data_loaded = pyqtSignal(object) def __init__(self, param): super().__init__() self.param = param def do_work(self): # Fai il lavoro qui # Controlla periodicamente self.is_cancelled for i in range(1000): if self.is_cancelled: logger.info("Lavoro cancellato") return None # ... processa dati ... return result # Uso: thread = MyDataLoader(param) thread.start() # Per cancellare: thread.cancel() thread.wait(2000) # Attendi max 2s cdtd|_g|_dS)NF)super__init__ _is_cancelled_cleanup_callbacks)self __class__s 4C:\PYTHON\MyICR_Suite\app\utils\cancelable_thread.pyr zCancelableThread.__init__;s/ ""$returnc|jS)u-Ritorna True se il thread è stato cancellato)r rs r is_cancelledzCancelableThread.is_cancelled@s !!rcbt|jjdd|_dS)ux Richiede la cancellazione del thread. Il thread si fermerà al prossimo check di is_cancelled. z: Cancellazione richiestaTN)loggerinfor__name__r rs rcancelzCancelableThread.cancelEs2  t~.IIIJJJ!rcallbackc:|j|dS)a Registra una callback da chiamare in caso di cancellazione. Args: callback: Funzione da chiamare senza parametri Example: def close_db(): db.close() thread.register_cleanup(close_db) N)rappend)rrs rregister_cleanupz!CancelableThread.register_cleanupMs! &&x00000rc td)u0 Override questo metodo nelle sottoclassi per implementare il lavoro. Ricordati di controllare periodicamente self.is_cancelled. Returns: Il risultato del lavoro (può essere None se cancellato) Raises: Exception: Se si verificano errori z,Le sottoclassi devono implementare do_work())NotImplementedErrorrs rdo_workzCancelableThread.do_work\s""PQQQrc( |jrCt|jjd |jdSt|jjd|}|jrr< data_loadedr'r*r+r,r-r.s rr"zDataLoaderThread.do_works   4 HD4FHHIII %T%;;(:;;F$ . %%f---M    LL8Q884L H H H   $ $SVV , , ,44444 s4A"" B=,AB88B=) rr3r4r5robjectrBrr r"r8r9s@rr;r;sn"*V$$K$H$$$$$$rr;cZeZdZdZeeZeeZde ffd Z dZ xZ S) QueryThreada, Thread specializzato per query database con supporto cancellazione. Features aggiuntive rispetto a DataLoaderThread: - Gestione connessione database - Cleanup automatico connessioni - Progress tracking opzionale Example: def run_query(db_mgr, filters): query = "SELECT * FROM table WHERE year = :year" return db_mgr.execute_query(query, filters) thread = QueryThread(run_query, db_mgr, filters={'year': 2024}) thread.query_completed.connect(on_results) thread.start() query_funccrt||_||_||_dS)z Args: query_func: Funzione che esegue la query *args: Argomenti posizionali per query_func **kwargs: Argomenti keyword per query_func N)r r rF query_args query_kwargs)rrFargsr?rs rr zQueryThread.__init__s7 $"rc|jrdStd|jj |j|ji|j}|js|j||S#t$rQ}t d|d|j t|Yd}~dSd}~wwxYw)zEsegue la queryNzEsecuzione query: zErrore query: Tr$) rrrrFrrHrIquery_completedr'r*r+r,r-r.s rr"zQueryThread.do_works   4 C)ACCDDD $T_doK9JKKF$ 2$))&111M    LL-!--L = = =   $ $SVV , , ,44444 s9A,, C6ACC) rr3r4r5rrCrLintprogress_updatedrr r"r8r9s@rrErEs|$!j((O!z# #8 # # # # # #rrEFthreadwait_msforcec|r|sdSt|dr;td|jj|||}|sT|rRt|jjd| |ddS|S)u( Termina un thread in modo sicuro. Args: thread: Thread da terminare wait_ms: Millisecondi da attendere per graceful shutdown force: Se True, usa terminate() se il thread non si ferma Returns: True se il thread è stato fermato, False altrimenti TrzCancellazione graceful di z* non terminato gracefully, force terminateiF) isRunninghasattrrrrrrwaitwarning terminate)rPrQrRfinisheds rsafe_terminate_threadrZs ))++tvx   L1A1JLLMMM {{7##H &*3___``` Du Or)rQthreadsctdt|d|D](}|r$t|dr|)|D]}|r||rh||sSt|jj d|d| |ddS)z Cleanup di multipli thread in parallelo. Args: *threads: Thread da pulire wait_ms: Tempo di attesa per thread Example: cleanup_threads(thread1, thread2, thread3, wait_ms=3000) z Cleanup di z threadrz non terminato entro msiN) rrlenrUrrTrVrWrrrX)rQr[rPs rcleanup_threadsr_s KK3c'll333444  gfh//  MMOOO!!  !f&&(( !;;w'' !&"2";]]RY]]]^^^  """ C   !!r)rOF)r5logging PyQt6.QtCorerrtypingrrr getLoggerrrr r;rErMr7rZr_rArrrds_  ,,,,,,,,&&&&&&&&&&  8 $ $tUtUtUtUtUwtUtUtUn11111'111h55555"555t'Ct@7;!!!g!!!!!!!r