0

我有一个程序,它有一个用户界面,用户可以通过它选择显示方式和进行小配置。它还有一个后台程序,不断地从网络中读取数据并更新数据来显示。

现在我把它们放在一个进程中:后台程序:

    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 中按下单选按钮时,程序必须过滤队列中的数据并显示在 table 小部件中:

用户界面操作:

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);

        }



    }

}

所以队列非常少,后台程序非常频繁(每秒近 500 次)。也就是说,队列将在 1 秒内被写入 500 次,但会不时由用户显示。
我想将这些函数分成两个线程并一起运行,一个是更新和更新数据,一个是显示。
如果我不使用任何锁或互斥锁,用户可能会得到错误的数据,但如果我强制写入数据过程每次都进入临界区并离开临界区,这将是一个严重的过载。:)
我应该使用 CRITICAL_SECTION 还是其他东西,有什么相关的建议吗?(我的话对你来说可能很冗长:),我只希望得到一些提示:)

4

1 回答 1

2

我将“Recv”函数放在另一个 QObject 派生类中,将其放在其他 QThread 而不是主 gui 线程下,并将“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 回答