Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Gr1f0nn
242 / 162 / 74
Регистрация: 30.09.2012
Сообщений: 690
#1

Реализация многопоточности в GUI приложении - C++

07.12.2014, 03:11. Просмотров 459. Ответов 6
Метки нет (Все метки)

Здравствуйте!

Заранее извиняюсь за, возможно, глупые вопросы по поводу этой темы, но они все-таки возникли ^_^

Стоит задача создать несколько потоков, которые будут добавлять объекты базового класса и наследника в класс-контейнер, а также извлекать их оттуда (в данном случае выводить на экран).

Шаблон контейнера:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
#ifndef BOX_H
#define BOX_H
#include <iostream>
#include <cstring>
#include <string>
#include "struct.h"
#include "manager.h"
#include <mutex>
using namespace std;
 
template <class X> struct cell;
template <class X> class box_it;
 
template <class X> class box
{
public:
    typedef cell<X>                          node;
    typedef box_it<X>                        iterator;
private:
    cell<X>
                *head,
                *tail;
    int
                size_;
public:
    box() { head = tail = NULL; size_ = 0; }
    box(const box &a) {
        node *temp;
        temp = a.head;
        head = tail = NULL;
        size_ = 0;
        while (temp != NULL) {
            push_back(temp->data);
            temp = temp->next;
        }
    }
 
    ~box() {
        clear();
        }
 
    void clear() {
        node
                *temp;
        while(head != NULL)
        {
            temp = head;
            head = head->next;
            delete temp;
        }
        head = tail = NULL;
        size_ = 0;
    }
 
    void push_back(const X a) {
        std::mutex      mute;
        mute.lock();
        cell<X> *p = new cell<X>;
        p->data = a;
        if (!head) {
            head = tail = p;
            tail->next = tail->prev = NULL;
        } else {
            tail->next = p;
            p->prev = tail;
            tail = p;
            tail->next = NULL;
        }
        size_++;
        mute.unlock();
    }
 
    void push_front(const X x)
    {
        std::mutex      mute;
        node
                *temp;
        mute.lock();
        temp = new node;
        temp->data = x;
        if (!head) {
            tail = head = temp;
            tail->prev = tail->next = NULL;
        } else {
            temp->next = head;
            head->prev = temp;
            head = temp;
        }
        size_++;
        mute.unlock();
    }
 
    void pop_back() {
        std::mutex      mute;
        mute.lock();
        node
                *temp;
        if (head) {
            temp = tail;
            tail = temp->prev;
            tail->next = NULL;
            delete temp;
        }
        size_--;
        mute.unlock();
    }
 
    void pop_front()
    {
        std::mutex      mute;
        mute.lock();
        node
                *temp;
        if (head) {
            temp = head;
            head = temp->next;
            head->prev = NULL;
            delete temp;
        }
        size_--;
        mute.unlock();
    }
 
    box_it<X> begin() { return box_it<X>(head); }
 
    box_it<X> end() { return box_it<X>(tail->next); }
 
    box<X>& operator=(const box<X> &a) {
        if (this != &a) {
            clear();
            node
                        *temp;
            temp = a.head;
            head = tail = NULL;
            size_ = 0;
            while (temp != NULL) {
                push_back(temp->data);
                temp = temp->next;
            }
        }
        return *this;
    }
 
    void erase(box_it<X> p)
    {
        cell<X>
                *temp;
        temp = p.temp;
        if (p == begin()) {
            pop_front();
        } else {
            if (p == end()) {
                pop_back();
            } else {
                if (p != begin() && p != end()) {
                    temp->prev->next = temp->next;
                    temp->next->prev = temp->prev;
                    delete temp;
                }
            }
        }
        size_--;
    }
 
    int size() const
    {
        return size_;
    }
 
    bool empty()
    {
        if (head) {
            return 0;
        } else {
            return 1;
        }
    }
 
    box_it<X> operator[] (int i)
    {
        cell<X>
                *temp;
        int
                j;
        if (!empty())
            if (i >= 1 && i <= size()) {
                temp = head;
                for( j=1 ; j<i ; j++ ) {
                    temp = temp->next;
                }
                return box_it<X>(temp);
            }
        return NULL;
    }
 
    box_it<X> operator() (int i)
    {
        return ((*this)[i]);
    }
 
    friend box<X> operator+(const box<X> b,  X i)
    {
        box<X> temp;
        temp = b;
        temp.push_back(i);
        return temp;
    }
 
    friend box<X> operator+( X i, const box<X> b)
    {
        return (b + i);
    }
 
    friend box<X> operator -(box<X> b, int i)
    {
        box<X> temp;
        temp = b;
        box_it<X> p = temp[i];
        temp.erase(p);
        return temp;
    }
 
    friend box<X> operator -(int i, box<X> b)
    {
        return (b - i);
    }
 
    box<X> &operator+=(X i)
    {
        push_front(i);
        return *this;
    }
 
    box<X> &operator-=(int i)
    {
        *this = *this - i;
        return *this;
    }
 
    box<X> &operator--()
    {
        pop_back();
        return *this;
    }
 
    box<X> operator--(int notused)
    {
        box<X> temp = *this;
        --(*this);
        return temp;
    }
 
};
#endif // BOX_H


Dialog.h
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#ifndef DIALOG_H
#define DIALOG_H
 
#include <QDialog>
#include <QMessageBox>
#include <fstream>
#include "box.h"
#include "infod.h"
#include <thread>
#include <windows.h>
#include <QThread>
 
namespace Ui {
class Dialog;
}
 
class Dialog : public QDialog
{
    Q_OBJECT
 
public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();
 
private slots:
    void on_addLast_clicked();
 
    void on_addBegin_clicked();
 
    void on_deleteAll_clicked();
 
    void on_show_clicked();
 
    void on_deleteLast_clicked();
 
    void on_deleteFirst_clicked();
 
    void on_deleteCurr_clicked();
 
    void on_type_activated(const QString &arg1);
 
    void on_save_clicked();
 
    void on_read_clicked();
 
    void on_edit_clicked();
 
private:
    Ui::Dialog *ui;
};
 
#endif // DIALOG_H


Что у меня получилось (как мне кажется, правильно):
Это реализовать потоки добавления объектов классов с информацией
C++
1
2
3
4
 u = new info(data);
            std::thread         thr1(&box<info*>::push_back,&ob,u);
            //ob=ob + u;
            thr1.join();
Что не получилось:
Хочу сделать фоновый поток, который бы постоянно обновлял экран и выводил все изменения. Как я понял, это надо делать вызывая поток не .join(), а .detach() , так как эта функция как раз делает его фоновым.
Если пишу так:
C++
1
2
3
4
            std::thread show(&Dialog::on_show_clicked,this);
            show.join();
// или
            show.detach();
, то не работает, так как эта функция является приватным слотом.
Пытался сделать так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class my_thread : public QThread
{
    Q_OBJECT
public:
    void run(){
        ///????  Пробовал реализовать бесконечный цикл, но это явно не то, что надо сделать
    }
signals:
    void func()
    {
        ////???
    }
 
};
 
my_thread thr_show;
QObject::connect(&thr_show,SIGNAL(func()),&w,SLOT(on_show_clicked()));
}
В main.cpp и не только. Тоже не работает.
В чем моя ошибка?

И возник еще один вопрос. Как передать параметры функции, используя стандартную библиотеку C++ для потоков я понял, а вот как сделать это, используя метод с созданием класса, который наследует QThread, не совсем. Я же не могу передать какой-либо параметр в функцию run()? Она тогда потеряет свою "виртуальную" природу и станет просто перегруженной, да и мне все равно придется реализовывать чистую виртуальную функцию run() без параметров в своем классе.

Заранее спасибо за помощь!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.12.2014, 03:11
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Реализация многопоточности в GUI приложении (C++):

Реализация многопоточности в консоли - C++
Доброго времени суток. Не могу разобраться в многопоточности. Реализовано перемещение по меню с помощью клавиш, и с помощью мыши. Надо...

Создание GUI в приложении с FreeGlut - C++
Добрый день. Мне поставлена задача добавить поля ввода и несколько кнопок в приложение. Приложение загружает файл формата obj и на основе...

Реализация запрета ввода любых символов кроме цифр в консольном приложении - C++
Здравствуйте, помогите пожалуйста реализовать запрет ввода любых символов кроме цифр в консольном приложении, считающем корни квадратного...

Как запустить GUI приложение (например, notepad.exe) без отображения GUI? - C++
Добрый день. Интересует есть ли такая возможность, как запустить GUI приложение (например, notepad.exe) без отображения GUI?

О многопоточности - C++
Интересно, стало, а сколько всего потоков я могу открыть в своем проекте, существуют ли какие нибудь ограничения? и от чего зависит...

Синхронизации многопоточности - C++
добрый день, пытаюсь сделать синхронизацию потом на примере producer\consumer, но что-то не выходит, я в consumere сделал ожидания...

6
Gr1f0nn
242 / 162 / 74
Регистрация: 30.09.2012
Сообщений: 690
07.12.2014, 03:11  [ТС] #2
dialog.cpp
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
#include "dialog.h"
#include "ui_dialog.h"
 
static box<info*> ob;
Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    ui->deleteCurr->hide();
    ui->name->hide();
    ui->nameLine->hide();
}
 
Dialog::~Dialog()
{
    delete ui;
}
 
void Dialog::on_addLast_clicked()
{
    string data, name;
    info *u;
    if(ui->type->currentText() == "Message")
    {
        if(ui->messageLine->text() != "")
        {
            data = ui->messageLine->text().toStdString();
            u = new info(data);
            std::thread         thr1(&box<info*>::push_back,&ob,u);
            //ob=ob + u;
            thr1.join();
            QMessageBox::information(this,"Information","Element added!",QMessageBox::Ok);
            ui->messageLine->setText("");
            ui->deleteCurr->show();
            on_show_clicked();
        }
        else QMessageBox::warning(this,"Warning","Please, enter your message!",QMessageBox::Ok);
    }
    if(ui->type->currentText() == "Message + name")
    {
        if(ui->messageLine->text() != "" && ui->nameLine->text() != "")
        {
            data = ui->messageLine->text().toStdString();
            name = ui->nameLine->text().toStdString();
            u = new infoD(data,name);
            std::thread         thr1(&box<info*>::push_back,&ob,u);
            //ob=ob + u;
            thr1.join();
            QMessageBox::information(this,"Information","Element added!",QMessageBox::Ok);
            ui->messageLine->setText("");
            ui->nameLine->setText("");
            ui->deleteCurr->show();
            on_show_clicked();
        }
        else QMessageBox::warning(this,"Warning","Please, enter your message!",QMessageBox::Ok);
    }
}
 
void Dialog::on_addBegin_clicked()
{
    string data, name;
    info *u;
    if(ui->type->currentText() == "Message")
    {
        if(ui->messageLine->text() != "")
        {
            data = ui->messageLine->text().toStdString();
            u = new info(data);
            //ob+=u;
            std::thread thr(&box<info*>::push_front,&ob,u);
            thr.join();
            QMessageBox::information(this,"Information","Element added!",QMessageBox::Ok);
            ui->messageLine->setText("");
            ui->deleteCurr->show();
            on_show_clicked();
        }
        else QMessageBox::warning(this,"Warning","Please, enter your message!",QMessageBox::Ok);
    }
    if(ui->type->currentText() == "Message + name")
    {
        if(ui->messageLine->text() != "" && ui->nameLine->text() != "")
        {
            data = ui->messageLine->text().toStdString();
            name = ui->nameLine->text().toStdString();
            u = new infoD(data,name);
            //ob+=u;
            std::thread thr(&box<info*>::push_front,&ob,u);
            thr.join();
            QMessageBox::information(this,"Information","Element added!",QMessageBox::Ok);
            ui->messageLine->setText("");
            ui->nameLine->setText("");
            ui->deleteCurr->show();
            on_show_clicked();
        }
        else QMessageBox::warning(this,"Warning","Please, enter your message!",QMessageBox::Ok);
    }
}
 
 
 
void Dialog::on_deleteAll_clicked()
{
   // std::thread thr1(ob);
    std::thread thr1(&box<info*>::clear, &ob);
    if(!ob.empty())
    {
        //ob.clear();
        thr1.join();
        QMessageBox::information(this,"Information","All elements deleted!",QMessageBox::Ok);
        ui->deleteCurr->hide();
        on_show_clicked();
    }
    else
        QMessageBox::warning(this,"Information","List empty!",QMessageBox::Ok);
}
 
void Dialog::on_show_clicked()
{
    if(ob.empty())
    {
        ui->console->clear();
        QMessageBox::warning(this,"Information","List empty!",QMessageBox::Ok);
    }
    else
    {
        ui->console->clear();
        box<info*>::iterator el = ob.begin();
        do
        {
            QString msg = QString::fromStdString((*el)->get_message());
            ui->console->addItem(msg);
            el++;
        }
        while(el != NULL);
    }
}
 
void Dialog::on_deleteLast_clicked()
{
    if(!ob.empty())
    {
        --ob;
        QMessageBox::information(this,"Information","Element deleted!",QMessageBox::Ok);
        on_show_clicked();
    }
    else QMessageBox::warning(this,"Information","List empty",QMessageBox::Ok);
    if(ob.empty()) ui->deleteCurr->hide();
}
 
void Dialog::on_deleteFirst_clicked()
{
    if(!ob.empty())
    {
        ob.pop_front();
        QMessageBox::information(this,"Information","Element deleted!",QMessageBox::Ok);
        on_show_clicked();
    }
    else QMessageBox::warning(this,"Information","List empty",QMessageBox::Ok);
    if(ob.empty()) ui->deleteCurr->hide();
}
 
void Dialog::on_deleteCurr_clicked()
{
    QListWidgetItem *current = ui->console->currentItem();
    if(current)
    {
        QString temp = current->text();
        box<info*>::iterator el = ob.begin();
        while(QString::fromStdString((*el)->get_message()) != temp)
        {
            el++;
        }
        if(QString::fromStdString((*el)->get_message()) == temp)
        {
            ob.erase(el);
            QMessageBox::information(this,"Information","Element deleted!",QMessageBox::Ok);
            on_show_clicked();
        }
        if(ob.empty()) ui->deleteCurr->hide();
    }
}
 
void Dialog::on_type_activated(const QString &arg1)
{
    if(arg1 == "Message")
    {
        ui->name->hide();
        ui->nameLine->hide();
    }
    if(arg1 == "Message + name")
    {
        ui->name->show();
        ui->nameLine->show();
    }
}
 
void Dialog::on_save_clicked()
{
    if(!ob.empty())
    {
        ofstream fout("fout");
        box<info*>::iterator el = ob.begin();
        do
        {
            fout << *el;
            el++;
        }
        while(el != ob.end());
        fout.close();
        QMessageBox::information(this,"Information","Saved!",QMessageBox::Ok);
    }
    else QMessageBox::warning(this,"Warning","List empty!",QMessageBox::Ok);
}
 
void Dialog::on_read_clicked()
{
    string
            type;
    info *p;
    ifstream fin("fout");
    if(fin)
    {
        do
        {
 
            fin >> type;
            if (type == "info") {
                p = new info();
            } else {
                p = new infoD();
            }
            fin >> p;
            std::thread thr_read(&box<info*>::push_back,&ob,p);
            //ob = ob + p;
            thr_read.detach();
           // Sleep(5000);
          //  std::thread show(&Dialog::on_show_clicked,this);
            //show.join();
        }
        while(!fin.eof());
        QMessageBox::information(this,"Information","Readed!",QMessageBox::Ok);
        ui->deleteCurr->show();
       // on_show_clicked();
    }
    else QMessageBox::warning(this,"Warning","Error!",QMessageBox::Ok);
}
 
void Dialog::on_edit_clicked()
{
    QListWidgetItem *current = ui->console->currentItem();
    if(current)
    {
        QString temp = current->text();
        box<info*>::iterator el = ob.begin();
        while(QString::fromStdString((*el)->get_message()) != temp)
        {
            el++;
        }
        if(QString::fromStdString((*el)->get_message()) == temp)
        {
            if((*el)->get_type() == "info")
            {
                if(ui->messageLine->text() != "")
                {
                    (*el)->set_m(ui->messageLine->text().toStdString());
                    QMessageBox::information(this,"Information","Element edited!",QMessageBox::Ok);
                }
                else QMessageBox::warning(this,"Warning","Please, enter your message!",QMessageBox::Ok);
            }
            else
            {
                if(ui->messageLine->text() != "" && ui->nameLine->text() != "")
                {
                    (*el)->set(ui->messageLine->text().toStdString(), ui->nameLine->text().toStdString());
                    QMessageBox::information(this,"Information","Element edited!",QMessageBox::Ok);
                }
                else QMessageBox::warning(this,"Warning","Please, enter your message!",QMessageBox::Ok);
            }
            on_show_clicked();
            ui->messageLine->setText("");
            ui->nameLine->setText("");
        }
    }
}
0
fit
14 / 14 / 0
Регистрация: 20.04.2010
Сообщений: 102
07.12.2014, 04:38 #3
определились бы какой инструментарий для работы с потоками хотите использовать, а то std::thread и QThread в одной куче
Цитата Сообщение от Gr1f0nn
, то не работает, так как эта функция является приватным слотом.
тогда сделайте публичным слотом
Цитата Сообщение от Gr1f0nn
И возник еще один вопрос. Как передать параметры функции, используя стандартную библиотеку C++ для потоков я понял, а вот как сделать это, используя метод с созданием класса, который наследует QThread, не совсем.
сделать эти параметры атрибутами класса потока. перед стартом потока передавать его объекту эти параметры.
кстати, есть мнение, что наследовать Qthread для создания потока - костыль, логичнее воспользоваться механизмом сигнал-слот
1
Gr1f0nn
242 / 162 / 74
Регистрация: 30.09.2012
Сообщений: 690
07.12.2014, 16:03  [ТС] #4
Цитата Сообщение от fit Посмотреть сообщение
определились бы какой инструментарий для работы с потоками хотите использовать, а то std::thread и QThread в одной куче
Хотел попробовать и тем и тем способом =)
+ не получалось связать поток std::thread с слотом обычным методом

Цитата Сообщение от fit Посмотреть сообщение
тогда сделайте публичным слотом
Вот об этом что-то я не подумал, спасибо!

Цитата Сообщение от fit Посмотреть сообщение
кстати, есть мнение, что наследовать Qthread для создания потока - костыль, логичнее воспользоваться механизмом сигнал-слот
Не могли бы Вы чуть-чуть поподробней пояснить, почему это не лучший способ?
Механизм сигнал-слот разве можно реализовать с помощью std::thread? Ведь, если я использую для этого QThread, то я пишу
C++
1
2
3
4
5
class some_thread : public QThread
{
Q_OBJECT
// some code
}
Тогда не получится сделать тоже самое, используя std::thread?

Добавлено через 49 минут
update:
С тем, почему наследовать класс Qthread не совсем верно, разобрался
0
fit
14 / 14 / 0
Регистрация: 20.04.2010
Сообщений: 102
07.12.2014, 16:48 #5
да не за что.
наследовать QThread и переопределять run неправильно с чисто методологической точки зрения. по сути, эта сущность предоставляет интерфейс для управления потоками ОС. если хотим воспользоваться интерфейсом - достаточно к нему просто обратиться, зачем наследовать? к тому же, смысл наследования в расширении функциональности базового класса. то есть, если вам нужно расширить/дополнить механизм работы Qt с потоками ОС - надо наследовать QThread. а если вам просто надо, чтобы какой-то участок кода выполнялся в отдельном потоке - такое наследование будет костылем. в последнем случае получится, что поведение сущности QThread вы расширяете поведением некоей другой "левой" сущности, не имеющей к назначению QThread (управление потоками ОС) никакого отношения.
логичнее вынести клиентский код в эту отдельную сущность и при помощи механизма сигнал-слот заставить его выполняться в другом потоке.
на практике это выглядит примерно так:

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class BlaBla {
 
public:
/*тут ваши параметры, какие хотели передать в поток*/
 
/*в этом методе код, который должен выполняться в отдельном потоке*/
run() {
 
/*тут что-то делаем*/
 
finished();
}
 
signals:
void finished(); //сигнализирует о необходимости завершения потока
 
}
 
QThread* t = new QThread;
BlaBla* b = new BlaBla;
b->moveToThread(t); //методы объекта b будут выполняться в отдельном потоке t
 
connect(t, SIGNAL(started()), mt, SLOT(run())); //старт потока начнется с вызова run()
connect(mt, SIGNAL(finished()), t, SLOT(quit())); //вызов finished() закроет поток t
 
t->start(); //запускаем поток, начнется выполнение BlaBla::run(), по его завершении поток будет закрыт
Добавлено через 13 минут
в коннектах вместо mt - b, конечно же. не знаю, что на меня нашло))
1
Gr1f0nn
242 / 162 / 74
Регистрация: 30.09.2012
Сообщений: 690
08.12.2014, 08:36  [ТС] #6
Вроде бы идею понял, а все равно возникла проблема.
Получается, мне, чтобы вынести в отдельный поток эту функцию:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void Dialog::on_show_clicked()
{
    if(ob.empty())
    {
        ui->console->clear();
        QMessageBox::warning(this,"Information","List empty!",QMessageBox::Ok);
    }
    else
    {
        ui->console->clear();
        box<info*>::iterator el = ob.begin();
        do
        {
            QString msg = QString::fromStdString((*el)->get_message());
            ui->console->addItem(msg);
            el++;
        }
        while(el != NULL);
    }
}
Мне нужно создать отдельный класс, в котором будет выполняться этот код?

Или я могу написать в конструкторе:
C++ (Qt)
1
2
3
4
5
6
7
8
9
Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    ui->deleteCurr->hide();
    ui->name->hide();
    ui->nameLine->hide();
}
Что-то вроде этого:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
    ui->setupUi(this);
    ui->deleteCurr->hide();
    ui->name->hide();
    ui->nameLine->hide();
    QThread *t = new QThread;
    this->moveToThread(t);
    connect(t,SIGNAL(started()),this,SLOT(on_show_clicked()));
    while(true)
    {
        t->start();
    }
?
Понятное дело, что именно так, как я это написал работать не будет ^_^ Никак не могу понять, как мне вынести эту единственную функцию в отдельный поток, чтобы она выполнялась до тех пор, пока я не закрою программу.
Неужели для этого нужен отдельный класс?

Добавлено через 3 минуты
Нашел один пример и попробовал сделать также:
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
class Worker : public QObject
{
    Q_OBJECT
    QThread workerThread;
 
private:
    box<info*> temp;
public:
    Worker(box<info*> &ob) { temp = ob; }
    Worker() {}
public slots:
    void doWork()
    {
        while(true)
        {
            box<info*>::iterator el = temp.begin();
            do
            {
                QString msg = QString::fromStdString((*el)->get_message());
                el++;
                emit resultReady(msg);
                QThread::msleep(1000);
            }
            while(el != NULL);
            el = temp.begin();
        }
    }
 
signals:
    void resultReady(const QString &result);
};
 
 
class Controller : public QObject
{
    Q_OBJECT
    QThread workerThread;
public:
    Controller(box<info*> &ob)
    {
        Worker *worker = new Worker(ob);
        worker->moveToThread(&workerThread);
        connect(&workerThread, SIGNAL(finished()),
                worker, SLOT(deleteLater()));
 
        connect(this, SIGNAL(startWorker()),
                worker, SLOT(doWork()));
 
        connect(worker, SIGNAL(resultReady(QString)),
                this, SIGNAL(handleResults(QString)));
        workerThread.start();
    }
    ~Controller()
    {
        workerThread.quit();
        workerThread.wait();
    }
 
signals:
    void handleResults(const QString &);
    void startWorker() {}
};


Вылезают ошибки:
threads.h:19: ошибка: undefined reference to `vtable for Worker'
threads.h:50: ошибка: undefined reference to `vtable for Controller'
collect2.exe:-1: ошибка: error: ld returned 1 exit status
В гугле, да и тут тоже, написано, что не реализован какой-то виртуальный метод класса QObject, но при этом в примере все работает без доп.реализаций других методов.

Добавлено через 38 секунд
Соответственно, чтобы запустить это пишу так:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    ui->deleteCurr->hide();
    ui->name->hide();
    ui->nameLine->hide();
 
    /// thread ///
    Controller *controller = new Controller(ob);
    connect(controller, SIGNAL(handleResults(QString)),
            ui->console, SLOT(addItem(QString)));
    controller->startWorker();
}
Добавлено через 14 часов 37 минут
Все, в принципе, разобрался как сделать это, правда, пока что получилось реализовать только с помощью наследования класса qthread.

У меня есть только один небольшой вопрос . Вот у меня есть функция чтения из файла. С маленьким файлом она работает нормально без использования отдельного потока, но если я создам файл, скажем, размером в 14 мб, то программа виснет, а если использую отдельный поток для этого, то нет. Это проблема в том, что алгоритм неправильно может быть реализован или что все уже "уперлось" в скорость этого алгоритма?
0
fit
14 / 14 / 0
Регистрация: 20.04.2010
Сообщений: 102
11.12.2014, 21:27 #7
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
Мне нужно создать отдельный класс, в котором будет выполняться этот код?
да незачем. можете поместить ее вызов в run (если наследуете от QThread) или объявить ее слотом и в нужном месте передавать отдельному потоку (в принципе в примере выше вы так и сделали, только зачем-то засунули вызов потока в бесконечный цикл - зачем??? от этого и не работало)
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
Это проблема в том, что алгоритм неправильно может быть реализован или что все уже "уперлось" в скорость этого алгоритма?
алгоритм ни при чем. манипуляции с файлами - всегда медленные операции. поэтому работу с большими файлами надо выносить в отдельный поток. и это не только файлов касается. в главном потоке у вас "крутится" интерфейс, естественно он будет виснуть, если в его же поток запихать решение какой-либо ресурсоемкой задачи
0
11.12.2014, 21:27
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.12.2014, 21:27
Привет! Вот еще темы с ответами:

Производительность многопоточности - C++
Доброго времени суток. Решил заняться многопоточностью, и натолкнулся на непонимание с производиельность Есть код в 2 потока: ...

изучение многопоточности - C++
с чего стоит начать изучение многопоточности? есть базовые знания по С++, основы ООП. пытался читать Назарр К., Рихтер Дж. - Windows via...

Сравнение многопоточности С++11 и WinAPI - C++
У меня скорее теоретический вопрос, чем практический. Есть ли разница работы с многопоточностью в С++11, и, например в WinAPI?...

Теория о многопоточности и многопроцессорности - C++
Ребят, возник вот такой вопрос: в каком случае многопоточность и многопроцессорность не будут работать?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru