zoukankan      html  css  js  c++  java
  • Qt开发中通过ResetEvent、CreateEvent、SetEvent、WaitForSingleObject实现同步的问题。

    以前没有用过C++的这个事件方式来进行同步的问题,这次尝试了一下感觉比较好用,在这里分享出来,作者的文件主要以实战为主,一些概念性的东西会忽略掉,因为这些东西在百度上太多了,这里就不赘述了。

    CreateEvent的意思是创建事件。

    ResetEvent的意思是指定的事件对象无信号。

    SetEvent的意思是设置事件的状态为有标记,释放任意等待线程。

    WaitForSingleObject的意思是状态挂起。

    简单的介绍了概念之后我们来看具体的操作。

    作者的程序为什么要用到这个东西呢?需要解决什么问题呢?

    A模块的函数中会用到B模块初始化的变量,A模块和B模块都是主界面程序的子类,程序启动以后A模块和B模块很快初始化,在A模块的定时器中就会马上用到B模块初始化的变量,这样就会有一种情况,B模块中的变量还没有初始化完成,A模块就在使用公用的这个变量,造成野指针以后程序就会崩溃,基于这种情况用到了上面的方式解决。

    首先在B模块中创建一个句柄(HANDLE),这里的B模块其实是一个线程。

    HANDLE             m_SortEvent; 

    然后在B模块的构造函数中进行初始化和创建对象。

    FireThread::FireThread(QObject *parent)
        : QThread(parent),
        m_SortEvent(INVALID_HANDLE_VALUE)
    {
        m_SortEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
        ResetEvent(m_SortEvent);
    }

    当然在析构函数中也要做好释放的工作。

    FireThread::~FireThread()
    {
        if (INVALID_HANDLE_VALUE != m_SortEvent)
        {
            CloseHandle(m_SortEvent);
        }
    }

    在线程的run函数会初始化一个Qlist。ResetEvent表示这里已经有信号了,将所有过程运行都完成了setEvent设置无信号,释放所有等待的线程。同时将QList和句柄通过emit发送出去。

        ResetEvent(m_SortEvent);  
    
        res = m_SortScanGun0->ConnectScanGun(m_pSettings->GetSortPLC()[SCANGUNADDR0].toString(), m_pSettings->GetSortPLC()[SCANPORT].toInt());
        if (!res)
        {
            BMSLogger::GetInstance().OutputLog(LogLevel::LOG_WARN, "Connect to ScanGun0 Device failed!!!");
        }
        else
        {
            BMSLogger::GetInstance().OutputLog(LogLevel::LOG_INFO, "Connect to ScanGun0 Device success!!!");
            
        }
        m_ListSorts.append(m_SortScanGun0);
    
        res = m_SortScanGun1->ConnectScanGun(m_pSettings->GetSortPLC()[SCANGUNADDR1].toString(), m_pSettings->GetSortPLC()[SCANPORT].toInt());
        if (!res)
        {
            BMSLogger::GetInstance().OutputLog(LogLevel::LOG_WARN, "Connect to ScanGun1 Device failed!!!");
        }
        else
        {
            BMSLogger::GetInstance().OutputLog(LogLevel::LOG_INFO, "Connect to ScanGun1 Device success!!!");
        }
        m_ListSorts.append(m_SortScanGun1);
    
        res = m_SortScanGun2->ConnectScanGun(m_pSettings->GetSortPLC()[SCANGUNADDR2].toString(), m_pSettings->GetSortPLC()[SCANPORT].toInt());
        if (!res)
        {
            BMSLogger::GetInstance().OutputLog(LogLevel::LOG_WARN, "Connect to ScanGun2 Device failed!!!");
        }
        else
        {
            BMSLogger::GetInstance().OutputLog(LogLevel::LOG_INFO, "Connect to ScanGun2 Device success!!!");
            
        }
        m_ListSorts.append(m_SortScanGun2);
    
        res = m_SortScanGun3->ConnectScanGun(m_pSettings->GetSortPLC()[SCANGUNADDR3].toString(), m_pSettings->GetSortPLC()[SCANPORT].toInt());
        if (!res)
        {
            BMSLogger::GetInstance().OutputLog(LogLevel::LOG_WARN, "Connect to ScanGun3 Device failed!!!");
        }
        else
        {
            BMSLogger::GetInstance().OutputLog(LogLevel::LOG_INFO, "Connect to ScanGun3 Device success!!!");
            
        }
        m_ListSorts.append(m_SortScanGun3);
    
        res = m_SortScanGun4->ConnectScanGun(m_pSettings->GetSortPLC()[SCANGUNADDR4].toString(), m_pSettings->GetSortPLC()[SCANPORT].toInt());
        if (!res)
        {
            BMSLogger::GetInstance().OutputLog(LogLevel::LOG_WARN, "Connect to ScanGun4 Device failed!!!");
        }
        else
        {
            BMSLogger::GetInstance().OutputLog(LogLevel::LOG_INFO, "Connect to ScanGun4 Device success!!!");
            
        }
        m_ListSorts.append(m_SortScanGun4);
    
        res = m_SortScanGun5->ConnectScanGun(m_pSettings->GetSortPLC()[SCANGUNADDR5].toString(), m_pSettings->GetSortPLC()[SCANPORT].toInt());
        if (!res)
        {
            BMSLogger::GetInstance().OutputLog(LogLevel::LOG_WARN, "Connect to ScanGun5 Device failed!!!");
        }
        else
        {
            BMSLogger::GetInstance().OutputLog(LogLevel::LOG_INFO, "Connect to ScanGun5 Device success!!!");
            
        }
        m_ListSorts.append(m_SortScanGun5);
    
        SetEvent(m_SortEvent);
        emit Signal_SendHandle(m_SortEvent);
        emit Signal_SendSortComm(m_ListSorts);

    这时在主界面程序中会用到Qt的信号和槽机制

        connect(m_pFireThread, &FireThread::Signal_SendSortComm, m_sortingWidget, &SortingWidget::Slot_GetFireThread, Qt::QueuedConnection);
        connect(m_pFireThread, &FireThread::Signal_SendHandle, m_sortingWidget, &SortingWidget::Slot_GetHandle, Qt::QueuedConnection);
    void SortingWidget::Slot_GetFireThread(QList<SortCommunication*> tmp_sorts)
    {
        m_Sorts = tmp_sorts;
    }
    
    void SortingWidget::Slot_GetHandle(HANDLE TmpHandle)
    {
        m_TmpSortHandle = TmpHandle;
    }

    这里的m_sortingWidget就相当于前面说到的A模块。

    在A模块的操作函数中会用到WaitForSingleObject()接口,这个函数有两个参数,一个是句柄,一个是时间,用在当前的位置表示函数已经挂起,在设置的时间内接收到句柄无信号的时候,挂起等待的线程就释放了,程序继续往下走。作者在这里设置的是2000ms。

        int res = WaitForSingleObject(m_TmpSortHandle, 2000);
        int m_grade = 0;
        if (m_Sorts[0]->IsConnected())
        {
            m_Sorts[0]->SendScaninfo();
        }
        TmpTrayCode.clear();
        Sleep(500);

    这样处理以后m_Sort[0]是从QList中取出来的数据,这样就不会出现因为QList中没有数据而导致野指针的情况,使程序崩溃了。

  • 相关阅读:
    UVALive 6909 Kevin's Problem 数学排列组合
    UVALive 6908 Electric Bike dp
    UVALive 6907 Body Building tarjan
    UVALive 6906 Cluster Analysis 并查集
    八月微博
    hdu 5784 How Many Triangles 计算几何,平面有多少个锐角三角形
    hdu 5792 World is Exploding 树状数组
    hdu 5791 Two dp
    hdu 5787 K-wolf Number 数位dp
    hdu 5783 Divide the Sequence 贪心
  • 原文地址:https://www.cnblogs.com/joorey/p/14792376.html
Copyright © 2011-2022 走看看