Domanda

Abbastanza nuovo per il threading e ho questa qlist che i thread condividono tra loro. Tutti hanno il loro spazio su cui possono lavorare e la GUI (il modello/vista) accede costantemente a questo elenco. Poi ottengo questo incidente che indica Qdatalist.size (). Il debug non mi aiuta davvero dal momento che non ho mai incontrato questo problema se passo attraverso il codice e quando sto provando a quale qlist si sta arrestando, non ci sono informazioni disponibili.

Quindi, la mia domanda è: è possibile ottenere la dimensione di QLIST e leggere gli oggetti allo stesso tempo? Gli oggetti nell'elenco sono sicuri del thread e non possono essere letti/scritti da diversi thread contemporaneamente.

Ottenere "0xc0000005: accesso alla violazione della violazione 0xfeeefefa." che mi punta a: inline int size () const in qlist.h

Cammino attraverso lo stack di chiamata e ho trovato questo:

QtCored4.dll!QListData::size()  Line 98 + 0x11 bytes    C++
QtNetworkd4.dll!QList<enum QNetworkReplyImplPrivate::InternalNotifications>::size()  Line 137 + 0x10 bytes  C++
QtNetworkd4.dll!QNetworkReplyImplPrivate::resumeNotificationHandling()  Line 444 + 0xe bytes    C++
QtNetworkd4.dll!QNetworkReplyImplPrivate::finished()  Line 797  C++
QtNetworkd4.dll!QNetworkAccessBackend::finished()  Line 313 C++
QtNetworkd4.dll!QNetworkAccessHttpBackend::replyFinished()  Line 739    C++
QtNetworkd4.dll!QNetworkAccessHttpBackend::qt_static_metacall(QObject * _o, QMetaObject::Call _c, int _id, void * * _a)  Line 86 + 0x8 bytes    C++
QtCored4.dll!QMetaCallEvent::placeMetaCall(QObject * object)  Line 525 + 0x1d bytes C++
QtCored4.dll!QObject::event(QEvent * e)  Line 1195 + 0x14 bytes C++
QtGuid4.dll!QApplicationPrivate::notify_helper(QObject * receiver, QEvent * e)  Line 4550 + 0x11 bytes  C++
QtGuid4.dll!QApplication::notify(QObject * receiver, QEvent * e)  Line 3932 + 0x10 bytes    C++
QtCored4.dll!QCoreApplication::notifyInternal(QObject * receiver, QEvent * event)  Line 876 + 0x15 bytes    C++
QtCored4.dll!QCoreApplication::sendEvent(QObject * receiver, QEvent * event)  Line 231 + 0x39 bytes C++
QtCored4.dll!QCoreApplicationPrivate::sendPostedEvents(QObject * receiver, int event_type, QThreadData * data)  Line 1500 + 0xd bytes   C++
QtCored4.dll!qt_internal_proc(HWND__ * hwnd, unsigned int message, unsigned int wp, long lp)  Line 496 + 0x10 bytes C++

Ogni thread sta avendo un gestore di rete che fa una refrigerazione di rete:

QThread Assert Failure in QmutexLocker: "Il puntatore QMUTEX è disallineato",

È stato utile?

Soluzione

Mi rendo conto che è possibile pre-allocare una qlist e lasciare che i thread operino su diverse aree di quell'elenco, ma secondo me penso che sia un cattivo modello da seguire.

Quando lavoro con QT (in realtà lavoro con Pyqt poiché sono un programmatore di Python), mi sento meglio utilizzare il meccanismo di segnale/slot che ti viene fornito e non condividere mai la memoria tra i thread. Ogni thread dovrebbe essere assegnato i propri dati direttamente alla creazione o nel tempo attraverso una coda che attende. Quando viene fatto con il suo lavoro o un pezzo di lavoro, può emettere un segnale con i dati. Avresti un singolo gestore che si collega a tutti i tuoi thread per ascoltare i dati per essere pronti.

Il risultato di questo modello è che non stai condividendo la memoria e non devi preoccuparti così tanto dei blocchi, ma piuttosto solo aspettare che i lavoratori seguano i loro dati sono pronti e un solo gestore sta raccogliendo e aggiornando il modello principale .

Detto questo, ecco un altro riferimento di qualcuno che usa una QLIST come memoria condivisa e sperimenta gli arresti anomali fino a quando non l'hanno bloccata: http://developer.qt.nokia.com/forums/viewthread/13049

Penso che quando le persone (me comprese) iniziano a lavorare con il thread l'impulso immediato è quello di usare i contenitori nello stesso modo in cui hanno sempre. Ma una volta che inizi a thread, aumenti immediatamente sia la complicazione della logica dei codici sia la capacità di bug. La sincronizzazione della memoria condivisa è un modo per avvicinarla, usando i mutex per bloccare le risorse prima dell'accesso. Ma penso che valga la pena menzionare un altro modo che sta comunicando.

Googles Go Language è stato costruito con uno dei suoi principi fondamentali: "Non comunicare condividendo la memoria; condividere la memoria comunicando" http://golang.org/doc/codewalk/sharemem/

GO volevo affrontare questo problema al centro comunicando la memoria sugli oggetti del canale, che assomigliano a segnale/slot in QT. Un componente ha un accesso locale esclusivo alla memoria e quindi trasmettelo a un altro componente su un canale. Questo Gurant non avrai condizioni di gara. Comunque pensavo solo che mi sarei affrontato su questo riferimento extra perché sento molto rilevante per i problemi di programmazione.

Altri suggerimenti

No, non possono Err, forse/probabilmente. La documentazione afferma che tutte le funzioni Qlist sono solo reentrant, e non thread-safe. Ora, normalmente leggere da una struttura condivisa dovrebbe essere thread-safe, ma in questo caso QT ha una documentazione esplicita e non vi è alcuna eccezione per la lettura. Pertanto è necessario supporre che non sia consentito e possa comportare errori.

Nota che a std::list Non soffre di questo problema e consente la lettura da più thread (la scrittura deve ovviamente essere ancora esclusiva).

Si noti che il threading QT nel complesso ha molti casi speciali, mi è stato spinto a scrivere "Requisiti per un'API filettata", Molti dei quali QT falliscono. Parte di questo è la storia e parte di questo si occupa di una varietà di hardware, ma in generale il threading QT deve essere trattato in particolare.


Poiché i documenti non sono coerenti (vedi commento), ho fatto una rapida revisione del codice sorgente QLIST. Funzioni semplici come "Begin", "Dimensioni" e "First" sembrano essere di sola lettura. Non modificano la struttura dei dati. Pertanto, se stanno causando un incidente è perché qualche altro thread sta modificando l'elenco contemporaneamente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top