0

私は、ユーザーが小さな設定を表示して実行する方法を選択するUiを備えたプログラムを持っています。また、ネットワークからデータを継続的に読み取り、表示するデータを更新するバックグラウンド手順もあります。

今、私はそれらを1つのプロセスに入れました:バックグラウンド手順:

    STATE MainWindow::Rcv()
    {

    DeviceMAP::iterator dev;

    for(dev= dev_map.begin(); dev!= dev_map.end(); dev++)
    {


        dev->second.rcvData();//receive data from the network, the time can be ignored.

        BitLog* log = new BitLog();
        dev->second.parseData(log);


        LogItem* logItem = new LogItem();
        logItem->time = QString::fromLocal8Bit(log->rcvTime.c_str());
        logItem->name = QString::fromLocal8Bit(log->basicInfo.getName().c_str());
        logItem->PIN = QString::fromLocal8Bit(log->basicInfo.getPIN().c_str()).toShort();

        delete log;
        add_logItem(logItem);

    }
    return SUCCESS;
}

add_logItem:

void MainWindow::add_logItem(LogItem* logItem)
{


    writeToFile(logItem);

    Device* r = getDevbyPIN(QString::number(logItem->PIN));

    if(r == NULL)return;

    devInfo_inside_widget::States state = logItem->state;

    bool bool_list[portsNum_X];
    for(int i =0; i < portsNum_X; i++)
    {
        bool_list[i] = 0;
    }

    for(int i = 0; i < portsNum; i++)
    {
        bool_list[i] = (logItem->BITS[i/8] >> (7 - i%8)) & 0x1;
    }

    r->refresh(state, logItem->time, bool_list);//update data inside...state, time , BITS...

    IconLabel* icl = getIConLabelByDev(r);//update data
    icl->refresh(state);


    logDisplayQueue.enqueue(logItem);//write queue here

    int size = logDisplayQueue.size();

    if(size > 100)
    {
        logDisplayQueue.dequeue();//write queue here
    }

}

上記のセクションではまだUI操作を扱っていませんが、ユーザーがUIのラジオボタンを押すと、プログラムはキュー内のデータをフィルタリングして、テーブルウィジェットに表示する必要があります。

UI操作:

void MainWindow::filter_log_display(bool bol)
{

    row_selectable = false;
    ui->tableWidget->setRowCount(0);//delete table items all
    row_selectable = true;

    int size_1 = logDisplayQueue.size() - 1;

    ui->tableWidget->verticalScrollBar()->setSliderPosition(0);

    if(size_1+1 < 100)
    {
        ui->tableWidget->setRowCount(size_1 + 1);
    }
    else
    {
        ui->tableWidget->setRowCount(100);//display 100 rows at most
    }


    if(bol)//filter from logDisplayQueue and display unworking-state-log rows
    {

        int  index = 0;
        for(int queue_i = size_1; queue_i >= 0; queue_i--)
        {

            LogItem* logItem = (LogItem*)logDisplayQueue.at(queue_i); // read queue here

            if(logItem->state == STATE_WORK || logItem->state == STATE_UN)continue;


            QString BITS_str = bits2Hexs(logItem->BITS);

            ui->tableWidget->setItem(index, 0, new QTableWidgetItem(logItem->time));//time
            ui->tableWidget->setItem(index, 1, new QTableWidgetItem(logItem->name));//name
            ui->tableWidget->setItem(index, 2, new QTableWidgetItem(BITS_str));//BITS

            if(queue_i == oldRowItemNo)ui->tableWidget->selectRow(index);
            index++;
        }

        ui->tableWidget->setRowCount(index);

    }
    else//display all rows
    {

        for(int queue_i = size_1, index = 0; queue_i >= 0; queue_i--, index++)
        {

            LogItem* logItem = (LogItem*)logDisplayQueue.at(queue_i);                      //read queue here

            QString BITS_str = bits2Hexs(logItem->BITS);//
            finish = clock();

            ui->tableWidget->setItem(index, 0, new QTableWidgetItem(logItem->time));//time
            ui->tableWidget->setItem(index, 1, new QTableWidgetItem(logItem->name));//name
            ui->tableWidget->setItem(index, 2, new QTableWidgetItem(BITS_str));//BITS

            if(queue_i == oldRowItemNo)ui->tableWidget->selectRow(index);

        }



    }

}

したがって、キューは非常に小さく、バックグラウンド手順は非常に頻繁です(1秒あたり約500回)。つまり、キューは1秒間に500回書き込まれますが、ユーザーによって時間ごとに表示されます。
関数を2つのスレッドに分割し、それらを一緒に実行したいと思います。1つはデータの回転と更新、もう1つは表示です。
ロックやミューテックスを使用しない場合、ユーザーは間違ったデータを取得する可能性がありますが、データの書き込み手順を強制的にクリティカルセクションに入り、毎回クリティカルセクションを離れると、大きな過負荷になります。:)
CRITICAL_SECTIONまたは何か他のものを使用する必要がありますか、関連する提案はありますか?(私の言葉はあなたにとって冗長かもしれません:)、私はいくつかのヒントだけを望んでいます:)

4

1 に答える 1

2

「Recv」関数を別のQObject派生クラスに配置し、メインGUIスレッドではなく他のQThreadの下に配置して、「logItemAdded(LogItem * item)」シグナルをメインウィンドウの「addLogItem(LogItem * item)」スロットに接続します。

簡単で汚いヒント​​のために、私の概念コードは次のとおりです。

 #include <QObject>

class Logger : public QObject
{
    Q_OBJECT
public:
    Logger(QObject* parent=0);
    virtual ~Logger();
signals:
    void logItemAdded(LogItem* logItem);
public slots:
protected:
    void Rcv()
    {
        // ...

        // was "add_logItem(logItem)"
        emit logItemAdded(logItem);
    }
};

MainWindow::MainWindow(...)
{
    Logger logger = new Logger;

    // setup your logger

    QThread* thread = new QThread;
    logger->moveToThread(thread);
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    thread->start();
}

お役に立てれば。

幸運を。

于 2012-10-15T03:43:22.093 に答える