Russian Qt Forum
Ноябрь 24, 2024, 01:38 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: вопрос по поводу qthread  (Прочитано 6531 раз)
koldun90
Крякер
****
Offline Offline

Сообщений: 345


Просмотр профиля
« : Июнь 30, 2017, 23:31 »

Здравствуйте разрабатываю приложение появилось необходимость вынести в поток отдельно действие которое будет повторяться каждый раз при вставке носителя
фрагмент mainwindow.cpp
mythread-класс в котором выполняется действие
Код
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---класс в котором выполняется действие
« Последнее редактирование: Июль 01, 2017, 09:47 от koldun90 » Записан
qate
Супер
******
Offline Offline

Сообщений: 1177


Просмотр профиля
« Ответ #1 : Июль 01, 2017, 19:33 »

зачем Qt::DirectConnection ?
что значит "Qtconcurent:run но он запускает поток, а удалить поток не может." ?

и делай пример-проект, вроде все должно работать ок
Записан
koldun90
Крякер
****
Offline Offline

Сообщений: 345


Просмотр профиля
« Ответ #2 : Июль 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.

Смысл в том что я вставляю носитель и каждый раз --функция которая что-то делает(в данном случае) ищет имя(которое получает на вход от главного потока) должна быть в отдельном потоке обработана и передать данные в основной поток. Заем поток должен корректно завершиться--сразу после отработки функции. Но почему -то не выходит
Записан
qate
Супер
******
Offline Offline

Сообщений: 1177


Просмотр профиля
« Ответ #3 : Июль 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
т.е. можно и прогресс и отмену иметь


Записан
koldun90
Крякер
****
Offline Offline

Сообщений: 345


Просмотр профиля
« Ответ #4 : Июль 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 строка пустая
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #5 : Июль 02, 2017, 12:56 »

Значит, управление ещё не успело дойти до getResult.
А вообще в коде мало смысла - вотчер созданный на стеке бесполезен
Записан
koldun90
Крякер
****
Offline Offline

Сообщений: 345


Просмотр профиля
« Ответ #6 : Июль 02, 2017, 21:48 »

хм странно когда прогоняю в отладчики данные записываются, без отладки переменные пустые
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #7 : Июль 02, 2017, 22:19 »

Значит, бага в коде. В конкаренте багов нет:)
Записан
koldun90
Крякер
****
Offline Offline

Сообщений: 345


Просмотр профиля
« Ответ #8 : Июль 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-пишется пустота
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #9 : Июль 02, 2017, 22:41 »

Уберите вооще вотчер, result() и так дожидается заверщения операции
Записан
koldun90
Крякер
****
Offline Offline

Сообщений: 345


Просмотр профиля
« Ответ #10 : Июль 02, 2017, 22:46 »

future--переменная класса ------QFuture <QString> future;
Код
C++ (Qt)
future=QtConcurrent::run(this,&MainWindow::getnameusbdevice,hardwareserial);
QString gg=future.result();

все тоже самое....
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.359 секунд. Запросов: 22.