ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Qt开发中通过ResetEvent、CreateEvent、SetEvent、WaitForSingleObject实现同步的问题。

2021-05-21 09:33:46  阅读:175  来源: 互联网

标签:Qt GetInstance LogLevel res WaitForSingleObject SetEvent pSettings BMSLogger Dev


以前没有用过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中没有数据而导致野指针的情况,使程序崩溃了。

 

标签:Qt,GetInstance,LogLevel,res,WaitForSingleObject,SetEvent,pSettings,BMSLogger,Dev
来源: https://www.cnblogs.com/joorey/p/14792376.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有