Название: вопрос по поводу qthread
Отправлено: koldun90 от Июнь 30, 2017, 23:31
Здравствуйте разрабатываю приложение появилось необходимость вынести в поток отдельно действие которое будет повторяться каждый раз при вставке носителя фрагмент mainwindow.cppmythread-класс в котором выполняется действие C++ (Qt) QThread *thread=new QThread(); mythread *work=new mythread(); work->moveToThread(thread); //слот получающий имя устройства при старте потока connect(thread,SIGNAL(started()),work,SLOT(friendlyname())); //передаем имя устройства для поиска в класс connect(this,SIGNAL(setname(QString)),work,SLOT(setfind(QString)),Qt::DirectConnection); // после отработки функции она посылает нам сигнал с дружественным именем connect(work,SIGNAL(finis(QString)),this,SLOT(friname(QString)),Qt::DirectConnection); connect(work,SIGNAL(fan()),thread,SLOT(quit()),Qt::QueuedConnection); connect(work,SIGNAL(fan()),work,SLOT(deleteLater()),Qt::QueuedConnection); connect(thread,SIGNAL(finished()),thread,SLOT(deleteLater()),Qt::QueuedConnection); emit setname(hardwareserial); //передаем в поток данные thread->wait(); thread->start(); mythread.cpp --там выполняются все действия C++ (Qt) #include "mythread.h" mythread::mythread(QObject *parent) : QObject(parent) { } void mythread::setfind(QString ser) { serial=ser; } void mythread::friendlyname() { //нахождение имени VARIANT vtProp2; VARIANT vtProp4; IWbemLocator *pLoc = NULL; IWbemServices *pSvc= NULL; IWbemClassObject *pclsObj = NULL; //Создаем объект IWbemLocator HRESULT hres; hres = CoInitializeEx(0,COINIT_APARTMENTTHREADED); if (FAILED(hres)) { cout << "Failed to initialize COM library. Error code = 0x" << hex << hres << endl; //return listdevice; // Program has failed. } hres = CoInitializeSecurity( NULL, -1, // COM authentication NULL, // Authentication services NULL, // Reserved RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation NULL, // Authentication info EOAC_NONE, // Additional capabilities NULL // Reserved ); // if (FAILED(hres)) // { // cout << "security. Error code = 0x" // << hex << hres << endl; // //return listdevice; // Program has failed. // } hres = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc); if (FAILED(hres)) { cout << "create inst loc. Error code = 0x" << hex << hres << endl; //return listdevice; // Program has failed. } hres = pLoc->ConnectServer( _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace NULL, // User name. NULL = current user NULL, // User password. NULL = current 0, // Locale. NULL indicates current NULL, // Security flags. 0, // Authority (for example, Kerberos) 0, // Context object &pSvc // pointer to IWbemServices proxy ); if (FAILED(hres)) { cout << "connectserver error. Error code = 0x" << hex << hres << endl; //return listdevice; // Program has failed. } IEnumWbemClassObject* pEnumerator = NULL; ULONG uReturn = 0; hres = CoSetProxyBlanket( pSvc, // Indicates the proxy to set RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx NULL, // Server principal name RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx NULL, // client identity EOAC_NONE // proxy capabilities ); if (FAILED(hres)) { cout << "proxyblanket. Error code = 0x" << hex << hres << endl; //return listdevice; // Program has failed. } hres = pSvc->ExecQuery( bstr_t("WQL"), bstr_t("SELECT * FROM Win32_DiskDrive"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); if (FAILED(hres)) { cout << "execquery. Error code = 0x" << hex << hres << endl; //return listdevice; // Program has failed. } while (pEnumerator) { HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if(0 == uReturn) { break; } hr=pclsObj->Get(L"PNPDeviceID", 0, &vtProp4, 0, 0); hr=pclsObj->Get(L"Model",0,&vtProp2,0,0); BSTR rr=vtProp4.bstrVal; // QString pnpdeviceid((QChar*)rr,::SysStringLen(rr)); //QString pnpp((QChar*)pnp,::SysStringLen(pnp)); //сравниваем два номера pnpdeviceid в случае если номер совпадает //значит устройство является сменным носителем ифнормации if (pnpdeviceid.contains(serial)) { BSTR g=vtProp2.bstrVal; QString friendlyname((QChar*)g,::SysStringLen(g)); emit finis(friendlyname); } } if (pLoc) pLoc->Release(); if (pSvc) pSvc->Release(); if (pclsObj) pclsObj->Release(); if (pEnumerator) pEnumerator->Release(); CoUninitialize(); emit fan(); //заканчиваем поток }
Не понятно собственно как корректно дождаться завершения действия в потоке и произвести закрытие и удаления потока , а также рабочего класса. Пробовал использовать Qtconcurent:run но он запускает поток, а удалить поток не может. А мне нужно чтобы действия в потоке выполнялись каждый раз при ставке носителя в этот метод из главного потока передается серийный номер устройства serial-перемеенная класса C++ (Qt) void mythread::setfind(QString ser) { serial=ser; }
далее в friendlyname происходит поиск номера, испускается сигнал C++ (Qt) emit finis(friendlyname); //передаем в главную форму
который передает в главную форму имя найденного устройства затем испускается сигнал fan() по котолрому должно закончиться действие в потоке. но почему то поток не уничтожается. Действие в потоке выполняются корректно серийный номер находится--- испускается сигнал finis(friendlyname) затем происходит выход из цикла while и испускается сигнал fan() Помогите добиться корректного завершения потока и корректно удаления указателей для которых выделяется память динамически. При этом основной поток должен ждать пока не закончиться выполнение в отдельном потоке функции по поиску имени mythread::friendlyname(); PS: чтоб не путаться mythread---класс в котором выполняется действие
Название: Re: вопрос по поводу qthread
Отправлено: qate от Июль 01, 2017, 19:33
зачем Qt::DirectConnection ? что значит "Qtconcurent:run но он запускает поток, а удалить поток не может." ?
и делай пример-проект, вроде все должно работать ок
Название: Re: вопрос по поводу qthread
Отправлено: koldun90 от Июль 01, 2017, 19:46
Qt::DirectConnection использую к это нашел в "правильном использовании qthread"
Note that the QFuture returned by QtConcurrent::run() does not support canceling, pausing, or progress reporting. The QFuture returned can only be used to query for the running/finished status and the return value of the function.
Смысл в том что я вставляю носитель и каждый раз --функция которая что-то делает(в данном случае) ищет имя(которое получает на вход от главного потока) должна быть в отдельном потоке обработана и передать данные в основной поток. Заем поток должен корректно завершиться--сразу после отработки функции. Но почему -то не выходит
Название: Re: вопрос по поводу qthread
Отправлено: qate от Июль 01, 2017, 23:14
> Qt::DirectConnection использую к это нашел в "правильном использовании qthread"
где ?
> Note that the QFuture returned by QtConcurrent::run() does not support canceling, pausing, or progress reporting. The QFuture returned can only be used to query for the running/finished status and the return value of the function.
это не совсем так, см. http://www.prog.org.ru/topic_23042_0.html т.е. можно и прогресс и отмену иметь
Название: Re: вопрос по поводу qthread
Отправлено: koldun90 от Июль 02, 2017, 09:05
http://blog.harrix.org/article/4826 если запускаю C++ (Qt) QFuture <QString> future; QFutureWatcher<QString> watch; future=QtConcurrent::run(this,&MainWindow::getnameusbdevice,hardwareserial); watch.setFuture(future); QString gg=future.result();
на выходе из функции MainWindow::getnameusbdevice проверяю в отладчике что возвращает имя устройства а в gg строка пустая
Название: Re: вопрос по поводу qthread
Отправлено: Авварон от Июль 02, 2017, 12:56
Значит, управление ещё не успело дойти до getResult. А вообще в коде мало смысла - вотчер созданный на стеке бесполезен
Название: Re: вопрос по поводу qthread
Отправлено: koldun90 от Июль 02, 2017, 21:48
хм странно когда прогоняю в отладчики данные записываются, без отладки переменные пустые
Название: Re: вопрос по поводу qthread
Отправлено: Авварон от Июль 02, 2017, 22:19
Значит, бага в коде. В конкаренте багов нет:)
Название: Re: вопрос по поводу qthread
Отправлено: koldun90 от Июль 02, 2017, 22:27
хм в чем может быть проблема вот вызов функции C++ (Qt) future=QtConcurrent::run(this,&MainWindow::getnameusbdevice,hardwareserial); watch.setFuture(future); watch.waitForFinished(); QString gg=future.result();
вот сама функция C++ (Qt) QString MainWindow::getnameusbdevice(QString serial) { VARIANT vtProp2; VARIANT vtProp4; QString drl; IWbemLocator *pLoc = NULL; IWbemServices *pSvc= NULL; IWbemClassObject *pclsObj = NULL; //Создаем объект IWbemLocator HRESULT hres; hres = CoInitializeEx(0,COINIT_APARTMENTTHREADED); if (FAILED(hres)) { cout << "Failed to initialize COM library. Error code = 0x" << hex << hres << endl; //return listdevice; // Program has failed. } hres = CoInitializeSecurity( NULL, -1, // COM authentication NULL, // Authentication services NULL, // Reserved RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation NULL, // Authentication info EOAC_NONE, // Additional capabilities NULL // Reserved ); // if (FAILED(hres)) // { // cout << "security. Error code = 0x" // << hex << hres << endl; // //return listdevice; // Program has failed. // } hres = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &pLoc); if (FAILED(hres)) { cout << "create inst loc. Error code = 0x" << hex << hres << endl; //return listdevice; // Program has failed. } hres = pLoc->ConnectServer( _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace NULL, // User name. NULL = current user NULL, // User password. NULL = current 0, // Locale. NULL indicates current NULL, // Security flags. 0, // Authority (for example, Kerberos) 0, // Context object &pSvc // pointer to IWbemServices proxy ); if (FAILED(hres)) { cout << "connectserver error. Error code = 0x" << hex << hres << endl; //return listdevice; // Program has failed. } IEnumWbemClassObject* pEnumerator = NULL; ULONG uReturn = 0; hres = CoSetProxyBlanket( pSvc, // Indicates the proxy to set RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx NULL, // Server principal name RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx NULL, // client identity EOAC_NONE // proxy capabilities ); if (FAILED(hres)) { cout << "proxyblanket. Error code = 0x" << hex << hres << endl; //return listdevice; // Program has failed. } hres = pSvc->ExecQuery( bstr_t("WQL"), bstr_t("SELECT * FROM Win32_DiskDrive"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); if (FAILED(hres)) { cout << "execquery. Error code = 0x" << hex << hres << endl; //return listdevice; // Program has failed. } // QString drl; while (pEnumerator) { HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if(0 == uReturn) { break; } hr=pclsObj->Get(L"PNPDeviceID", 0, &vtProp4, 0, 0); hr=pclsObj->Get(L"Model",0,&vtProp2,0,0); BSTR rr=vtProp4.bstrVal; //сравниваем pnpdeviceid РґРІСѓС… объектов // QString pnpdeviceid((QChar*)rr,::SysStringLen(rr)); //QString pnpp((QChar*)pnp,::SysStringLen(pnp)); //сравниваем два номера pnpdeviceid в случае если номер совпадает //значит устройство является сменным носителем ифнормации if (pnpdeviceid.contains(serial)) { BSTR g=vtProp2.bstrVal; QString friendlyname((QChar*)g,::SysStringLen(g)); drl=friendlyname; } } if (pLoc) pLoc->Release(); if (pSvc) pSvc->Release(); if (pclsObj) pclsObj->Release(); if (pEnumerator) pEnumerator->Release(); CoUninitialize(); qDebug()<<"FFFFF="<<drl; return drl; }
не пойму в чем проблема в отладчике drl--не пустое значение а после C++ (Qt) QString gg=future.result();
а в gg-пишется пустота
Название: Re: вопрос по поводу qthread
Отправлено: Авварон от Июль 02, 2017, 22:41
Уберите вооще вотчер, result() и так дожидается заверщения операции
Название: Re: вопрос по поводу qthread
Отправлено: koldun90 от Июль 02, 2017, 22:46
future--переменная класса ------QFuture <QString> future; C++ (Qt) future=QtConcurrent::run(this,&MainWindow::getnameusbdevice,hardwareserial); QString gg=future.result();
все тоже самое....
|