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

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

Страниц: [1] 2 3   Вниз
  Печать  
Автор Тема: Аварийное завершение программы при использованиии Concurrent API  (Прочитано 19799 раз)
AlekseyK
Гость
« : Октябрь 27, 2009, 19:24 »

Вобщем имеем такой код:
Код:
    QEventLoop loop;
    QFutureWatcher<void> watcher;
    connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit()));
    QFuture<void> future = QtConcurrent::run(this, &MyClass::MyMethod, parameters...);
    watcher.setFuture(future);
    loop.exec();

При использовании такой конструкции вылетает segmentation fault. Если просто вызвать MyMethod с параметрами, то всё работает без ошибок, но это неудобно т.к. в этом методе запускается продолжительный вычислительный процесс и хочется, чтобы он выполнялся в отдельном потоке. Если зкомментировать цикл и QFutureWatcher, то вылетает уже другая ошибка, но суть та же. Воспроизводится как в Qt 4.5.3, так и в 4.6.0-beta1, и в Windows, и в Linux.

В чём может быть проблема: это моя ошибка или баг Qt и надо им писать отчёт?

Думаю ещё запустить Valgrind, чтобы проверить нет ли где ошибки обращения к памяти в моём приложении.

Цитата: Вывод приложения:
ASSERT: "qApp && qApp->thread() == QThread::currentThread()" in file kernel\qapplication_win.cpp, line 895
QWaitCondition: Destroyed while threads are still waiting
Записан
Rcus
Гость
« Ответ #1 : Октябрь 27, 2009, 19:46 »

Ну вот именно это утверждение должно гарантировать что к функциям рисования будут обращаться только из главного потока, что происходит в другой системе тоже надо смотреть, а вообще так ли сложно запустить отладчик и узнать след стека вызовов?
Я тоже не любил отладчики, но после сеанса ловли SIGSEGV при инициализации фреймбуффера без отладочных символов (памяти не хватало) очень даже полюбил их (хотя без крайней необходимости использую только для посмертного изучения процесса)
Записан
AlekseyK
Гость
« Ответ #2 : Октябрь 27, 2009, 20:36 »

Ну вот именно это утверждение должно гарантировать что к функциям рисования будут обращаться только из главного потока
Понятно, этот момент я видимо пропустил в документации. Благодарю! Исправил. Я использовал QTextEdit для вывода отладочной информации из этой функции и... repaint(),  Смеющийся чтобы что-то увидеть пока идут вычисления, т.к. они выполнялись в том же потоке, теперь я благополучно убрал ui->errorEdit->repaint() за ненадобностью, всё работает! Спасибо.

P.S. Qt таки рулит! Подмигивающий
P.P.S. А чем всё-таки может быть связана такая особенность Qt Concurrent?
« Последнее редактирование: Октябрь 27, 2009, 21:34 от AlekseyK » Записан
AlekseyK
Гость
« Ответ #3 : Октябрь 29, 2009, 14:47 »

В винде продолжает вылетать, стек ни о чём ни говорит, всегда запускаю в отладчике пока что:

Код
0 ntdll!LdrDestroyOutOfProcessImage C:\WINDOWS\system32\ntdll.dll 0 0x7c8285f3
1 ntdll!LdrAddRefDll C:\WINDOWS\system32\ntdll.dll 0 0x7c82860c
2 ntdll!ZwClose C:\WINDOWS\system32\ntdll.dll 0 0x7c826d49
3 ?? C:\WINDOWS\system32\vfbasics.dll 0 0x00392f52
4 ?? 0 0x00000000
 

Цитата: Вывод приложения
ASSERT: "qApp && qApp->thread() == QThread::currentThread()" in file kernel\qapplication_win.cpp, line 895
QWaitCondition: Destroyed while threads are still waiting
QObject::killTimers: timers cannot be stopped from another thread

В чём может быть проблема?
Записан
AlekseyK
Гость
« Ответ #4 : Апрель 15, 2010, 16:48 »

Я нашёл: в моём методе оставался вызов:

ui->errorEdit->append(s);

Линукс с ним нормально работает, windows - вываливает ошибку. Я смотрю, что QtConcurrent может передавать информацию во вне только через progressText() и progressValue(). А как можно менять их значение в MyMethod?!
Записан
SABROG
Гость
« Ответ #5 : Апрель 15, 2010, 16:56 »

Линукс с ним нормально работает, windows - вываливает ошибку. Я смотрю, что QtConcurrent может передавать информацию во вне только через progressText() и progressValue(). А как можно менять их значение в MyMethod?!

Это особенность потоков. ОС ни при чем. Унаследуй свой класс от QObject'a и отсылай сигналы. progressValue() меняется автоматически, если ты используешь контейнеры/списки/листы в методе типа QtConcurrent::map(). Для QtConcurrent::run() он не сигналит:

Цитировать
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.
Записан
AlekseyK
Гость
« Ответ #6 : Апрель 15, 2010, 17:23 »

Это особенность потоков. ОС ни при чем. Унаследуй свой класс от QObject'a и отсылай сигналы.
А он так и унаследован - от QMainWindow, а MyMethod определён в нём, и в этом же классе в другом методе создаётся QFuture объект.

progressValue() меняется автоматически, если ты используешь контейнеры/списки/листы в методе типа QtConcurrent::map(). Для QtConcurrent::run() он не сигналит:
Понятно, будем разбираться с map: с run() всё так просто - запускаешь свою функцию... ЛЮБУЮ, и порядок! Подмигивающий Но что интересно в линуксе:
Код:
ui->errorEdit->append(s);
и
progressBar->setValue(i * 100 / cycles);
работают внутри MyMethod(), хотя похоже, что ошибки иногда всё-таки вылетают, а в винде отказывается категорически.

Цитировать
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.
Понятно, спасибо, не дочитал просто до этого места.
Записан
AlekseyK
Гость
« Ответ #7 : Апрель 15, 2010, 17:35 »

Блин, это ж для map придётся логику MyMethod() полностью менять?
Записан
AlekseyK
Гость
« Ответ #8 : Апрель 15, 2010, 17:56 »

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.qtcentre.org/threads/26861-QtConcurrent-i-need-advice? Подмигивающий

А что означала твоя фраза:
Код:
I solved my task himself, with signals and slots and using QtConcurrent::run(). 
?
Записан
AlekseyK
Гость
« Ответ #9 : Апрель 15, 2010, 19:58 »

Передалал код так:
Код:
    QEventLoop loop;
    QFutureWatcher<QString> watcher;
    connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit()));
    // Prepare cycles vector
    QVector<int> vector;
    for (int i = 0; i < cyclesCount; i++)
        vector.append(i);
    // Run thread
    watcher.setFuture(QtConcurrent::mapped(vector,  &MyClass::MyMethod));

не собирается. Ошибка:

Цитировать
no matching function for call to 'mapped(QVector<int>&, QString (MyClass::*)(int&))'

Чего ему не хватает? Или он методы класса не поддерживает?

MyClass, напомню,-  производный от QMainWindow и всё в нём происходит.
Объявление MyMethod:
QString MyMethod(int &cycleNo);
Записан
AlekseyK
Гость
« Ответ #10 : Апрель 15, 2010, 20:15 »

Блин, похоже он это не поддерживает и надо будет использовать QThread?
Записан
Kolobok
Гость
« Ответ #11 : Апрель 15, 2010, 22:07 »

#include <QtConcurrentMap>
Записан
AlekseyK
Гость
« Ответ #12 : Апрель 15, 2010, 23:59 »

#include <QtConcurrentMap>

Благодарствую, добавил. Но ошибка пока всё та же:

Цитировать
no matching function for call to ‘mapped(QVector<int>&, QString (MyMainWindow::*)(const int&))’
Записан
AlekseyK
Гость
« Ответ #13 : Апрель 16, 2010, 11:06 »

Ау, люди???!!! Есть идеи?! Или может у кого есть пример работающего собирающегося аналогичного кода, пожалуйста?
Записан
Kolobok
Гость
« Ответ #14 : Апрель 16, 2010, 12:41 »

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


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