Получение порядковых номеров элементов из расчета QtConcurrent Threaded

Пространство имен QtConcurrent действительно отлично подходит для упрощения управления многопоточными вычислениями. В целом, это прекрасно работает, и я смог использовать QtConcurrent run (), map () и другие варианты так, как они описаны в API.

Общая цель:

Я хотел бы запросить, отменить () или pause () численное вычисление из QML. Пока это работает так, как мне хотелось бы, за исключением того, что я не могу получить доступ к порядковым номерам в расчете. Вот ссылка, которая описывает аналогичную настройку QML.

Ниже приведено изображение из небольшого тестового приложения, которое я создал для инкапсуляции того, что я пытаюсь сделать:

введите описание изображения здесь

В приведенном выше примере расчет почти завершен, и все ядра были поставлены в очередь для правильной работы, как видно из системного запроса:

введите описание изображения здесь

Но то, что я действительно хотел бы сделать, это использовать порядковые номера из данного списка элементов В сам многопоточный расчет. Например, одним из подходов может быть простая установка порядковых номеров непосредственно в QList или QVector (другие контейнеры C ++ STL также могут работать), например, так:

void TaskDialog::mapTask()
{
// Number of times the map function will be called:
int N = 5;

// Prepare the vector that we operate on with mapFunction:
QList<int> vectorOfInts;
for (int i = 0; i < N; i++) {
vectorOfInts << i;
}

// Start the calc:
QFuture<void> future = QtConcurrent::map(vectorOfInts, mapFunction);
_futureWatcher.setFuture(future);
//_futureWatcher.waitForFinished();
}

Расчет неблокируемый со строкой: _futureWatcher.waitForFinished(); закомментировано, как показано в коде выше. Обратите внимание, что при настройке в качестве неблокирующего вычисления поток графического интерфейса реагирует, и индикатор выполнения обновляется по желанию.

Но когда во время вычисления запрашиваются значения в контейнере QList, кажется, что это неинициализированные значения мусора, которые можно ожидать, если массив не инициализирован должным образом.

Ниже приведен пример функции, которую я вызываю:

void mapFunction(int& n)
{
// Check the n values:
qDebug() << "n = " << n;
/* Below is an arbitrary task but note that we left out n,
* although normally we would want to use it): */
const long work = 10000 * 10000 * 10;
long s = 0;
for (long j = 0; j < work; j++)
s++;
}

И выход qDebug() является:

n =  30458288
n =  204778
n =  270195923
n =  0
n =  270385260

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

Теперь, если я раскомментирую _futureWatcher.waitForFinished(); Затем я получаю ожидаемые значения (порядок не имеет значения):

n =  0
n =  2
n =  4
n =  3
n =  1

Но в этом случае, с _futureWatcher.waitForFinished(); включен, мой поток GUI заблокирован, и индикатор выполнения не обновляется.

В чем тогда будет преимущество использования QtConcurrent :: map () с включенной блокировкой, если цель не блокировать основной поток GUI?

Во-вторых, как можно получить правильные значения n в неблокирующем случае, позволяя GUI оставаться отзывчивым и обновлять ли индикатор выполнения?

Моим единственным вариантом может быть прямое использование QThread, но я хотел воспользоваться всеми приятными инструментами, которые были нам установлены в QtConcurrent.

Мысли? Предложения? Другие опции? Благодарю.


РЕДАКТИРОВАТЬ: Спасибо user2025983 за понимание, которое помогло мне решить эту проблему. Суть в том, что мне сначала нужно было динамически выделить QList:

QList<int>* vectorOfInts = new QList<int>;
for (int i = 0; i < N; i++)
vectorOfInts->push_back(i);

Далее vectorOfInts передается по ссылке на функцию map путем разыменования указателя, например:

QFuture<void> future = QtConcurrent::map(*vectorOfInts, mapFunction);

Также обратите внимание, что прототип mapFunction остается прежним:

void mapFunction(int& n)

И тогда все работает правильно: графический интерфейс остался отзывчивым, индикатор выполнения обновлен, значения n все правильно и т.д., БЕЗ необходимости добавлять блокировку через функцию:

_futureWatcher.waitForFinished();

Надеюсь, что эти дополнительные детали могут помочь кому-то еще.

2

Решение

Проблема в том, что ваш QList выходит за рамки, когда mapTask() отделки.
Так как mapFunction(int &n) принимает параметр по ссылке, он получает ссылки на целочисленные значения, которые теперь являются частью массива, который находится вне области видимости! Таким образом, компьютер может свободно делать с этой памятью все, что угодно, поэтому вы видите значения мусора. Если вы просто используете целочисленные параметры, я бы рекомендовал передавать параметры по значению, и тогда все должно работать.

В качестве альтернативы, если вы должны передать по ссылке, вы можете сделать так, чтобы futureWatcher удалил массив после его завершения.

    QList<int>* vectorOfInts = new QList<int>;
// push back into structure
connect(_futureWatcher, SIGNAL(finished()), vectorOfInts, SLOT(deleteLater()));
// launch stuff
QtConcurrent::map...
// profit
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]