我应该使用CRITICAL_SECTION吗?

时间:2012-10-15 01:16:28

标签: multithreading qt user-interface locking

我有一个具有Ui的程序,用户可以选择显示和执行小配置的方式。它还有一个后台程序,它不断从网络读取数据并更新要显示的数据。

现在我将它们放在一个过程中: 后台程序:

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

        }



    }

}

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

1 个答案:

答案 0 :(得分: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();
}

希望这有帮助。

祝你好运。