2012-03-09 12 views
5

Sto cercando una soluzione per pianificare la cancellazione di un oggetto attraverso i thread. I documenti su come si comportano deleteLater non sono completamente chiari. Posso chiamare questa funzione in un thread che non è il proprietario dell'oggetto?QObject :: deleteLater attraverso un QThread

Ad esempio, l'oggetto X è di proprietà del thread A e in Thread B mi piacerebbe avere l'oggetto X cancellato. Poiché l'oggetto potrebbe trovarsi all'interno dell'elaborazione dell'evento al momento (nella Discussione A), non posso cancellarlo in modo sicuro finché non torna al ciclo dei messaggi. Se chiamo deleteLater da Thread B, tuttavia i documenti sembrano indicare che verrà eliminato non appena Thread B tornerà al loop dei messaggi.

Attualmente ho l'approccio di avere un segnale emesso nel thread A che è collegato a uno slot che chiama deleteLater. Mi chiedo se c'è forse un modo più semplice per farlo - se davvero posso semplicemente chiamare deleteLater da qualsiasi thread.

+0

In Qt è possibile modificare quale thread possiede un oggetto. Ti aiuterebbe? – sashoalm

+0

Ecco come l'oggetto entra nella discussione. –

risposta

0

deleteLater() significa solo che l'oggetto verrà eliminato dopo che tutti i segnali/slot int sono stati trattati nel loop eventi corrente (cioè ThreadB).

Quindi, se nessun altro slot ha bisogno di ObjectX in ThreadB, equivale a un semplice delete.

Se è possibile eliminare l'oggetto o meno e come verrà gestito in ThreadA dipende dalla logica dell'app.

Se ObjectX è l'oggetto principale del thread, inviare il segnale quit() a ThreadA è la strada da percorrere.

+0

Ci saranno molti oggetti di questo tipo, il thread è un oggetto distinto. Stai confermando che deleteLater si verifica effettivamente solo nel thread corrente (quindi non è sicuro per il mio utilizzo). –

+0

@ edA-qamort-ora-y Dipende dalla versione Qt che si sta utilizzando. Vedi il commento di 'Lol4t0' sotto la tua domanda. –

6

Mentre deleteLater() non è sicuro per sé, è possibile richiamare in object s' threadA con meta chiamata:

metaObject()->invokeMethod(object, "deleteLater", Qt::QueuedConnection); 

Poi, sarà sicuro.

+0

Sono preoccupato che i documenti dicano solo "loop eventi principale" per la connessione in coda qui (molto diversa da come funziona solitamente una coda di connessione). Questo è solo un errore di doc, questo sarà effettivamente come un normale segnale inserito nell'altro thread? –

+0

@ edA-qamort-ora-y, beh, sembra essere un bug di documentazione, e ho cancellato oggetti con tale codice, ma mentre studiavo il codice sorgente Qt proprio ora ho trovato che la chiamata diretta a 'deleteLater' è sicura come chiamata, quindi nella realizzazione attuale il lavoro di chiamata diretta e il comportamento delle versioni future possono sorprendere in entrambi i casi. – Lol4t0

+0

Ho rintracciato anche il codice sorgente e deleteLater pubblica semplicemente un evento e tiene traccia del fatto che gli eventi inviati verranno sempre inviati al proprietario del thread del destinatario. Argh! Perché i dottori non potevano dire la stessa cosa, quindi non mi preoccuperei di questo ...:( –

5

Guardando allo Qt 4 code e Qt 5 code, deleteLater() invoca appena QCoreApplication::postEvent() che è esplicitamente dichiarato thread-safe. Quindi, dovrebbe andare bene chiamarlo direttamente. Poiché la coda degli eventi viene elaborata nel thread del proprietario dell'oggetto, la cancellazione avverrà nel thread A.

Se si desidera fare completamente affidamento sul comportamento documentato, è sufficiente utilizzare postEvent().

Problemi correlati