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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: приоритеты  (Прочитано 12996 раз)
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


Просмотр профиля
« : Май 30, 2017, 23:34 »

Скажите, возможно ли дать родительскому
потоку (GUI) более низкиий приоритет чем дочернему?
Если да, то не могли бы привести пример как это сделать.
Сасибо!

Записан
ksk-
Самовар
**
Offline Offline

Сообщений: 178



Просмотр профиля
« Ответ #1 : Май 31, 2017, 05:17 »

http://doc.qt.io/qt-4.8/qthread.html#setPriority
Разве нет?
Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


Просмотр профиля
« Ответ #2 : Май 31, 2017, 10:21 »


Похоже что нет Непонимающий
Может я конечно делаю неправильно что-то.

Берем поток и инкрементируем в нем счетчик.
Отображаем значение счетчика на индикаторе два раза в секунду.
Потоки создаются и запускаются по нажатию кнопки.
Когда запускается поток, ему устанавливается приоритет.
Вот код
Код
C++ (Qt)
#include <QThread>
#include <QMutex>
#include <QDebug>
 
class Thread : public QThread
{
   Q_OBJECT
 
public:
   explicit Thread(QObject *parent = 0);
   virtual ~Thread();
 
public:
   int cnt();
   bool term();
   void setTerm(bool );
 
protected:
   void run();
 
public slots:
 
private:
   QMutex mutex_cnt;
   QMutex mutex_term;
   int m_cnt;
   bool m_term;
 
signals:
 
};
 
 
Thread::Thread(QObject *parent) :
   QThread(parent)
{
   m_cnt = 0;
   m_term = false;
}
 
Thread::~Thread()
{
}
 
void Thread::setTerm(bool val)
{
   mutex_term.lock();
   m_term = val;
   mutex_term.unlock();
}
 
bool Thread::term()
{
   mutex_term.lock();
   int val = m_term;
   mutex_term.unlock();
   return val;
}
 
int Thread::cnt()
{
   mutex_cnt.lock();
   int val = m_cnt;
   mutex_cnt.unlock();
   return val;
}
 
void Thread::run()
{
   for(;;)
   {
       msleep(2);
       if(!term())
           break;
       mutex_cnt.lock();
       m_cnt++;
       mutex_cnt.unlock();
   }
}
 
 
 
#include <QMainWindow>
#include <QTimer>
#include "thread.h"
 
namespace Ui {
   class MainWindow;
}
 
class MainWindow : public QMainWindow
{
   Q_OBJECT
 
public:
   explicit MainWindow(QWidget *parent = 0);
   ~MainWindow();
 
public slots:
   void clickedStart();
   void clickedStop();
   void updateView();
 
private:
   Ui::MainWindow *ui;
 
private:
   Thread *threadCnt1;
   Thread *threadCnt2;
 
   QTimer *timerView;
};
 
 
#include "mainwindow.h"
#include "ui_mainwindow.h"
 
MainWindow::MainWindow(QWidget *parent) :
   QMainWindow(parent),
   ui(new Ui::MainWindow)
{
   ui->setupUi(this);
 
   threadCnt1 = NULL;
   threadCnt2 = NULL;
 
   timerView = new QTimer(this);
   connect(timerView,SIGNAL(timeout()),this,SLOT(updateView()));
 
   connect(ui->pbStart,SIGNAL(clicked()),this,SLOT(clickedStart()));
   connect(ui->pbStop,SIGNAL(clicked()),this,SLOT(clickedStop()));
 
}
 
MainWindow::~MainWindow()
{
   delete ui;
   clickedStop();
}
 
void MainWindow::clickedStart()
{
   timerView->start(500);
 
   if(!threadCnt1){
       threadCnt1 = new Thread;
       threadCnt1->setTerm(true);
       threadCnt1->start(QThread::TimeCriticalPriority);
   }
 
   if(!threadCnt2){
       threadCnt2 = new Thread;
       threadCnt2->setTerm(true);
       threadCnt2->start(QThread::LowestPriority);
   }
}
 
void MainWindow::clickedStop()
{
   timerView->stop();
 
   if(threadCnt1){
       threadCnt1->setTerm(false);
       threadCnt1->quit();
       threadCnt1->wait();
       delete threadCnt1;
       threadCnt1 = NULL;
   }
 
   if(threadCnt2){
       threadCnt2->setTerm(false);
       threadCnt2->quit();
       threadCnt2->wait();
       delete threadCnt2;
       threadCnt2 = NULL;
   }
}
 
void MainWindow::updateView()
{
   ui->lcdCntThread1->display(threadCnt1->cnt());
   ui->lcdCntThread2->display(threadCnt2->cnt());
}
 
Во время раьоты программы значения счетчиков постоянно одинаковы, хотя приоритеты у потоков разные.
Может я конечно не прав,но получается что  в  Qt нельзя раздать приорететы потокам. Или это надо делать как-то по особеннолму?   
Записан
ksk-
Самовар
**
Offline Offline

Сообщений: 178



Просмотр профиля
« Ответ #3 : Май 31, 2017, 18:23 »

Ну тогда придётся написать платформозависимый код.

Например:
http://www.yonch.com/tech/82-linux-thread-priority или https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms686277(v=vs.85).aspx
« Последнее редактирование: Май 31, 2017, 18:26 от ksk- » Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


Просмотр профиля
« Ответ #4 : Май 31, 2017, 19:56 »

Ну тогда придётся написать платформозависимый код.

Например:
http://www.yonch.com/tech/82-linux-thread-priority или https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms686277(v=vs.85).aspx
Спасибо, попробую.
« Последнее редактирование: Май 31, 2017, 21:23 от demaker » Записан
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


Просмотр профиля
« Ответ #5 : Июнь 01, 2017, 14:17 »

Ну тогда придётся написать платформозависимый код.

Например:
http://www.yonch.com/tech/82-linux-thread-priority или https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms686277(v=vs.85).aspx
Спасибо, попробую.


К сожалению не помогло.
Пробовал для  Windows.
Функция  GetCurrentThread() в MainWondow и в run() потоках возвращает одинаковые значения.
Qt функция thread() возвращает разные значения указателей на потоки.
Не могу понять Непонимающий Непонимающий Непонимающий

Код:
Код
C++ (Qt)
MainWindow::MainWindow(QWidget *parent) :
   QMainWindow(parent),
   ui(new Ui::MainWindow)
{
   ui->setupUi(this);
 
   cnt = 0;
   threadCnt1 = NULL;
   threadCnt2 = NULL;
 
   timerView = new QTimer(this);
   connect(timerView,SIGNAL(timeout()),this,SLOT(updateView()));
 
   connect(ui->pbStart,SIGNAL(clicked()),this,SLOT(clickedStart()));
   connect(ui->pbStop,SIGNAL(clicked()),this,SLOT(clickedStop()));
 
   qDebug()<<"main thread_Qt = "<<thread();
   qDebug()<<"main thread_WINAPI = "<<GetCurrentThread();
}
 
 
void Thread::run()
{
   qDebug()<<"thread_Qt = "<<thread();
   qDebug()<<"thread_WINAPI = "<<GetCurrentThread();
   SetThreadPriority(GetCurrentThread(),m_priority);
   for(;;)
   {
       msleep(2);
       if(!term())
           break;
       mutex_cnt.lock();
       m_cnt++;
       mutex_cnt.unlock();
   }    
}
 
« Последнее редактирование: Июнь 01, 2017, 16:03 от demaker » Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #6 : Июнь 01, 2017, 16:43 »

Попробуйте убрать для начала "msleep(2);". И блокировок слишком много, потоки особо не конкурируют. Лучше сделайте пример, где потоки обращаются к одной переменной: один увеличивает её, другой уменьшает. Там должна быть заметна разница в приоритетах.
Записан

Пока сам не сделаешь...
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


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

Попробуйте убрать для начала "msleep(2);". И блокировок слишком много, потоки особо не конкурируют. Лучше сделайте пример, где потоки обращаются к одной переменной: один увеличивает её, другой уменьшает. Там должна быть заметна разница в приоритетах.

Попробовал как Вы сказали.
Один поток работает на увеличение значения, другой поток его уменьшает.
Результат примерно такой жe - иногда проскальзывает единица на экран, потом нуль.

Вот код:
Код
C++ (Qt)
 
//Global varibles
int varible;
QMutex mutex_varible;
 
 
MainWindow::MainWindow(QWidget *parent) :
   QMainWindow(parent),
   ui(new Ui::MainWindow)
{
   ui->setupUi(this);
 
   //cnt = 0;
   varible = 0;
   threadCnt1 = NULL;
   threadCnt2 = NULL;
 
   timerView = new QTimer(this);
   connect(timerView,SIGNAL(timeout()),this,SLOT(updateView()));
 
   connect(ui->pbStart,SIGNAL(clicked()),this,SLOT(clickedStart()));
   connect(ui->pbStop,SIGNAL(clicked()),this,SLOT(clickedStop()));
 
}
 
void MainWindow::clickedStart()
{
   timerView->start(1000);
 
   if(!threadCnt1){                
#ifdef __linux__
       threadCnt1 = new Thread(sched_get_priority_max(SCHED_FIFO));
#elif __WIN32__
       threadCnt1 = new Thread(THREAD_PRIORITY_TIME_CRITICAL);
#endif
       threadCnt1->setTerm(true);
       threadCnt1->start();
   }
 
   if(!threadCnt2){
#ifdef __linux__
       threadCnt2 = new Thread(sched_get_priority_min(SCHED_FIFO));
#elif __WIN32__
       threadCnt2 = new Thread(THREAD_PRIORITY_IDLE);
#endif
       threadCnt2->setTerm(true);
       threadCnt2->start();
   }
}
 
void MainWindow::clickedStop()
{
   varible = 0;
   timerView->stop();
 
   if(threadCnt1){
       threadCnt1->setTerm(false);
       threadCnt1->quit();
       threadCnt1->wait();
       delete threadCnt1;
       threadCnt1 = NULL;
   }
 
   if(threadCnt2){
       threadCnt2->setTerm(false);
       threadCnt2->quit();
       threadCnt2->wait();
       delete threadCnt2;
       threadCnt2 = NULL;
   }
}
 
void MainWindow::updateView()
{  
   mutex_varible.lock();
   ui->lcdGUIThread->display(varible);
   mutex_varible.unlock();
}
 
void Thread::run()
{
#ifdef __linux__
   pthread_t this_thread = pthread_self();
   struct sched_param params;
   params.sched_priority = m_priority;
   pthread_setschedparam(this_thread,SCHED_FIFO,&params);
#elif __WIN32__
   qDebug()<<"thread_Qt = "<<thread();
   qDebug()<<"thread_WINAPI = "<<GetCurrentThread();
   SetThreadPriority(GetCurrentThread(),m_priority);
#endif
 
   if(m_priority == THREAD_PRIORITY_TIME_CRITICAL){
       for(;;)
       {
           msleep(2);
           if(!term())
               break;
           //mutex_cnt.lock();
           //m_cnt++;
           //mutex_cnt.unlock();
 
           //mutex_varible.lock();
           varible++;
           //mutex_varible.unlock();
       }
   }
   else if(m_priority == THREAD_PRIORITY_IDLE){
       for(;;)
       {
           msleep(2);
           if(!term())
               break;
           //mutex_cnt.lock();
           //m_cnt++;
           //mutex_cnt.unlock();
 
           //mutex_varible.lock();
           varible--;
           //mutex_varible.unlock();
 
       }
   }
}
 
 
void MainWindow::updateView()
{  
   //mutex_varible.lock();
   ui->lcdGUIThread->display(varible);
   //mutex_varible.unlock();
}
 
« Последнее редактирование: Июнь 01, 2017, 17:47 от demaker » Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #8 : Июнь 01, 2017, 18:31 »

1. Приоритет потоку нужно задавать после его старта, об этом выводится отладочное сообщение.
2. Убрать "msleep(2);", это очень большая задержка, там ещё на блокировках и выводе переменной в lcdGUIThread много времени уходит.
3. Увеличить число знаков в ui->lcdGUIThread->setDigitCount(10);

Код
C++ (Qt)
void MainWindow::clickedStart()
{
   varible = 0;
 
   timerView->start(500);
 
   if(!threadCnt1){
       threadCnt1 = new Thread();
       threadCnt1->setTerm(true);
       threadCnt1->start();
       threadCnt1->setPriority(QThread::TimeCriticalPriority);
   }
 
   if(!threadCnt2){
       threadCnt2 = new Thread();
       threadCnt2->setTerm(true);
       threadCnt2->start();
       threadCnt2->setPriority(QThread::IdlePriority);
   }
}
 
void Thread::run()
{
   if(priority() == QThread::TimeCriticalPriority){
       for(;;)
       {
           //msleep(2);
           if(!term())
               break;
           //mutex_cnt.lock();
           //m_cnt++;
           //mutex_cnt.unlock();
 
           mutex_varible.lock();
           varible++;
           mutex_varible.unlock();
       }
   }
   else if(priority() == QThread::IdlePriority){
       for(;;)
       {
           //msleep(2);
           if(!term())
               break;
           //mutex_cnt.lock();
           //m_cnt++;
           //mutex_cnt.unlock();
 
           mutex_varible.lock();
           varible--;
           mutex_varible.unlock();
       }
   }
}
 

С таким кодом у меня нормально приоритеты потоков соблюдаются.
Записан

Пока сам не сделаешь...
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


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

1. Приоритет потоку нужно задавать после его старта, об этом выводится отладочное сообщение.
2. Убрать "msleep(2);", это очень большая задержка, там ещё на блокировках и выводе переменной в lcdGUIThread много времени уходит.
3. Увеличить число знаков в ui->lcdGUIThread->setDigitCount(10);

Код
C++ (Qt)
void MainWindow::clickedStart()
{
   varible = 0;
 
   timerView->start(500);
 
   if(!threadCnt1){
       threadCnt1 = new Thread();
       threadCnt1->setTerm(true);
       threadCnt1->start();
       threadCnt1->setPriority(QThread::TimeCriticalPriority);
   }
 
   if(!threadCnt2){
       threadCnt2 = new Thread();
       threadCnt2->setTerm(true);
       threadCnt2->start();
       threadCnt2->setPriority(QThread::IdlePriority);
   }
}
 
void Thread::run()
{
   if(priority() == QThread::TimeCriticalPriority){
       for(;;)
       {
           //msleep(2);
           if(!term())
               break;
           //mutex_cnt.lock();
           //m_cnt++;
           //mutex_cnt.unlock();
 
           mutex_varible.lock();
           varible++;
           mutex_varible.unlock();
       }
   }
   else if(priority() == QThread::IdlePriority){
       for(;;)
       {
           //msleep(2);
           if(!term())
               break;
           //mutex_cnt.lock();
           //m_cnt++;
           //mutex_cnt.unlock();
 
           mutex_varible.lock();
           varible--;
           mutex_varible.unlock();
       }
   }
}
 

С таким кодом у меня нормально приоритеты потоков соблюдаются.

Понял. Спасибо.
А поменять приоритет  потока gui так
Код:
 thread ()->setPriority (QThread::IdlePriority)
можно?
 
« Последнее редактирование: Июнь 01, 2017, 19:16 от demaker » Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



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

А поменять приоритет  потока gui так
Код:
thread ()->setPriority (QThread::IdlePriority)
можно?

Можно.
Записан

Пока сам не сделаешь...
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


Просмотр профиля
« Ответ #11 : Июнь 02, 2017, 09:59 »

А вот еще такой вопрос.  Строит глазки
Почему когда у меня было два потока с разными приоритетами. У каждого потока свой инкрементный счетчик.
То разницы значений счетчиков не было, хотя мне казалось , что у потока с более высоким приоритетом
значение счетчика должно быть больше. Разве нет Непонимающий (Или это связанно с тем что процессор не загружен.)
« Последнее редактирование: Июнь 02, 2017, 10:20 от demaker » Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



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

Причины те же (п. 1, 2). Если система свободна и потоки не конкурируют, то планировщик потоков ОС может и даёт им выполняться на равных условиях, не зависимо от их приоритетов, особенно на многоядерном процессоре. И с задержкой msleep(2) вы, в некоторой степени, синхронизируете потоки. С такой задержкой каждый из них выполнится порядка 500 раз в секунду, не зависимо от приоритета. И такая задержка намного больше времени выполнения "полезного кода". Грубо говоря, изменение счётчика выполняется за несколько микросекунд, а потом он спит 2000 микросекунд. И это с блокировками. Без блокировок разница может быть ещё на порядки больше.
Записан

Пока сам не сделаешь...
demaker
Птица говорун
*****
Offline Offline

Сообщений: 962


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

По поводу msleep.
Когда у меня его нет, то у меня отображение вообще не изменяется.
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



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

Тогда компилируемый проект выкладывайте, чтобы было с чем разбираться.
Записан

Пока сам не сделаешь...
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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