Con la cola de eventos para resolver el problema de la orden de las operaciones de QT GUI

Original: https://www.cnblogs.com/Philip-Tell-Truth/p/6295186.html

GUI problemas causados ​​por la secuencia de funcionamiento anormal

A veces usamos el tiempo para escribir programa de interfaz gráfica de usuario se encontrará con este problema: por ejemplo, en el proceso, se estableció una lista de interfaz gráfica de usuario. Esta lista se actualiza continuamente con el tiempo, y la operación leerá la lista de contenidos de la interfaz gráfica de usuario.

Si el programa es programas multi-hilo, pero sólo además de la interfaz gráfica de usuario de hilo no está funcionando, pero otros hilos que opera esta lista interfaz gráfica de usuario, entonces el problema es muy simple, basta con añadir bloqueo de exclusión mutua en él. Pero si el propio hilo de interfaz gráfica de usuario que también opera esta lista, entonces el problema es muy molesto.

Es fácil imaginar un escenario como el hilo GUI leer algunas de las entradas en la lista (por ejemplo, seleccionado), luego pase un puntero a un método de mantener a estas entradas, pero por desgracia en este momento otros hilos existe la necesidad de solicitud para eliminar algunas entradas en la lista, y algunas de estas entradas está incluido en nuestra selección, tenemos que saber cuándo entrar en el hilo de interfaz gráfica de usuario que operan casi todo el lenguaje de la interfaz gráfica de usuario de operación, entonces solo hemos elegido cuando se interrumpe ese método de entrada y, a continuación, elimine la entrada en el método, después de borrar las entradas devueltas una vez más con el método de entrada seleccionada, se seleccionaron algunas de las entradas se han suprimido, entonces antes de continuar, probablemente no satisfacer nuestras necesidades.

Si está utilizando Generalmente se usa C #, la gestión de memoria en JAVA que no tienen su propio idioma, que está bien, pero los resultados pueden estar equivocados, pero si tenemos que utilizar este C ++ para escribir su propia gestión de memoria, es probable que vamos a operar un objeto de memoria se libera, y el programa colapse a cabo, esta situación es que no queremos ver.

Con la cola de eventos para resolver el problema:

A continuación se representa mediante un diagrama de cómo diseñar la cola de eventos:

img

  Por supuesto, aunque la cifra es de sólo tres operaciones, si se desea, se puede diseñar más operaciones, como la lectura, se puede subdividir en información de entrada de la copia y la entrada correspondiente a la operación de contenido.

Después de un diseño de este tipo, es que algunas elimina medida el problema de interrumpir el funcionamiento de la interfaz gráfica de usuario (por ejemplo, el tipo que nos encontramos en nuestra visita es un destructor del problema objeto).

  En Qt podemos escribir: (ConnectionView este objeto es que he dicho anteriormente que la entrada)

class ItemsOpsBase
    {
    public:
        virtual void doOperation(ConnectionView *view) = 0;
        virtual ~ItemsOpsBase() = default;
    };
    
    class DeleteItem : public ItemsOpsBase
    {
    public:
        DeleteItem(qintptr target,qint32 connectionIndex)
            :ItemsOpsBase(), _target(target),_connectionIndex(connectionIndex){ }
        
        void doOperation(ConnectionView *view)override;
        ~DeleteItem() = default;
    private:
        qintptr _target;
        qint32 _connectionIndex;
    };
    
    class UpdatePulse :public ItemsOpsBase
    {
    public:
        UpdatePulse(qintptr descriptor,qint32 currentTime)
            :ItemsOpsBase(), _descriptor(descriptor),_currentTime(currentTime){  }
        
        void doOperation(ConnectionView *view)override;
        ~UpdatePulse() = default;
    private:
        qintptr _descriptor;
        qint32 _currentTime;
    };

class UpdateRemark : public ItemsOpsBase
    {
    public:
        UpdateRemark(qintptr descriptor, const QString &remark)
            : ItemsOpsBase(),_remark(remark),_descriptor(descriptor){  }
        
        void doOperation(ConnectionView *view)override;
        ~UpdateRemark() = default;
    private:
        QString _remark;
        qintptr _descriptor;
    };
    
    class TestConnection : public ItemsOpsBase
    {
    public:
        void doOperation(ConnectionView *view)override;
    };
class TestConnectionProducer : public QThread
    {
    public:
        void run()override;
    };
    
    class CopySelectedItemInformProducer :  public QThread
    {
    public:
        void run()override;
    };
    
    class DisconnectTargetsProducer : public QThread
    {
    public:
        void run()override;
    };
    
    class DeleteItemProducer :public QThread
    {
    public:
        DeleteItemProducer(qintptr target, qint32 connectionIndex)
            : QThread(),_target(target),_connectionIndex(connectionIndex) { }
        void run()override;
    private:
        qintptr _target;
        qint32 _connectionIndex;
    };
    
    class UpdatePulseProducer :public QThread
    {
    public:
        UpdatePulseProducer(qintptr descriptor, qint32 currentTime)
            :QThread(),_descriptor(descriptor),_currentTime(currentTime){  }
    protected:  
        void run()override;
    private:
        qintptr _descriptor;
        qint32 _currentTime;
    };
    
    class UpdateRemarkProducer : public QThread
    {
    public:
        UpdateRemarkProducer(qintptr descriptor, const QString &remark)
            :QThread(),_remark(remark),_descriptor(descriptor){ }
    protected:   
        void run()override;
    private:
        QString _remark;
        qintptr _descriptor;
    };
class ConsumerHelper :public QThread
    {
    public:
        ConsumerHelper(ConnectionView *view)
            :QThread(),_view(view){ }
        ~ConsumerHelper();
    protected:
        void run() override;
    private:
        ConnectionView *_view;
        
        ConsumerHelper(const ConsumerHelper &other) = delete;
        ConsumerHelper(const ConsumerHelper &&other) = delete;
        ConsumerHelper &operator=(const ConsumerHelper &other) = delete;
    };

  Y el código de cola de mutex:

static QQueue<QSharedPointer<ItemsOpsBase>> &opQueue()
{
       static QQueue<QSharedPointer<ItemsOpsBase>> queue;
       return queue;
}
    
static QSharedPointer<ItemsOpsBase> endOperation;

static QMutex &opQueueLock()
{
       static QMutex mutex;
       return mutex;
}
static QWaitCondition &opQueueIsAvailable()
{
       static QWaitCondition flag;
       return flag;
}

  ConsumerHelper es un hilo consumidor, ha estado monitoreando los movimientos de la cola, cuando se necesita una determinada operación, que puede desencadenar una operación de rosca del objeto, la operación correspondiente a unirse a la cola (¿Por qué necesito para abrir un hilo, con el fin de facilitar la mutua la exclusión), tales como los siguientes necesito una operación de eliminación:

  Retire la operación de código:

void DeleteItem::doOperation(ConnectionView *view)
    {
        qRegisterMetaType<qintptr>("qintptr");
        qRegisterMetaType<TcpConnectionHandler *>("TcpConnectionHandler *");
        QMetaObject::invokeMethod(view, "deleteConnection",Qt::QueuedConnection, Q_ARG(qintptr, _target), Q_ARG(qint32, _connectionIndex));
    }
void DeleteItemProducer::run()
    {
        QSharedPointer<ItemsOpsBase> op = QSharedPointer<ItemsOpsBase>(new DeleteItem(_target,_connectionIndex));
        
        QMutexLocker locker(&opQueueLock());
        opQueue().enqueue(op);
        opQueueIsAvailable().wakeOne();
    }

Los consumidores código roscados:

void ConsumerHelper::run()
    {
        forever
        {
            QSharedPointer<ItemsOpsBase> opPointer;
            
            {
                QMutexLocker locker(&opQueueLock());
                
                if (opQueue().isEmpty())
                    opQueueIsAvailable().wait(&opQueueLock());
                opPointer = opQueue().dequeue();
                
                if (opPointer == endOperation)
                    break;
            }
            {
                if(!opPointer.isNull())
                    opPointer->doOperation(_view);
            }
        }
    } 

    ConsumerHelper::~ConsumerHelper()
    {
        {
            QMutexLocker locker(&opQueueLock());
            while(!opQueue().isEmpty())
                opQueue().dequeue();
            
            opQueue().enqueue(endOperation);
            opQueueIsAvailable().wakeOne();
        }
        
        wait();//注意这里是wait在次线程上的
    }

  Esta vez sólo necesito para usar en lugar de una operación de eliminación:

DeleteItemProducer *deleteItemProducer = new DeleteItemProducer(target,index);
connect(deleteItemProducer, &QThread::finished, deleteItemProducer, &QThread::deleteLater);
deleteItemProducer->start();

Supongo que te gusta

Origin www.cnblogs.com/schips/p/12536427.html
Recomendado
Clasificación