Поделиться объектом между двумя лямбдами - PullRequest
2 голосов
/ 10 апреля 2019

Я пытаюсь разделить тот же объект (в моем случае, строку) между лямбдами, используя shared_ptr:

auto fileToLoad = make_shared<string>();
    StartAsync(
        [=]()
    {

        QDir dir(dirPath.c_str());
        QString fileExtension(fileExt.c_str());

        for (int i = 0; i < 150; i++)
        {
            auto files = dir.entryList(QStringList() << fileExtension << fileExtension.toUpper(), QDir::Files);
            if (!files.empty())
            {
                //fileToLoad.reset(new string(files.first().toUtf8().constData()));
                fileToLoad = make_shared<string>(files.first().toUtf8().constData());
                break;
            }

            this_thread::sleep_for(chrono::milliseconds(200));
        }
    },
        [=]()
    {
        if (fileToLoad == nullptr)
        {
            DisplayMessage("Timeout reached");
        }
        else
        {
            doFunc(*fileToLoad);
        }
    });

После многих попыток я все еще не смог заставить его работать так, как я хочу: сохранить fileToLoad в первой лямбде и использовать ее во второй.Или он не может быть скомпилирован из-за квалификаторов (const), или он компилируется, но fileToLoad остается пустым.

Как вы можете видеть, я пытаюсь уведомить, если файл появился в папке, используя функцию StartAsync,которая занимает 2 лямбда-выражения (эта функция в основном создает объекты QObject и перемещает их в фоновый поток, а затем устанавливает некоторые соединения между сигналами и слотами).

Edit:

StartAsync: принимает лямбда-задачи (длительная работа) и лямбда пост-задач (обновления пользовательского интерфейса)

void MainWidget::StartAsync(function<void()> func, function<void()> postTask)
{
    AsyncTask* task = new AsyncTask(func, [=]() { if (postTask != nullptr) { postTask(); HideProgressBar(); }});
    QThread* thread = new QThread();
    task->moveToThread(thread);

    connect(thread, &QThread::started, this, &MainWidget::ShowProgressBar);
    connect(thread, &QThread::started, task, &AsyncTask::RunTask);
    connect(task, &AsyncTask::TaskFinished, task, &AsyncTask::RunPostTask);
    connect(thread, &QThread::finished, task, &QObject::deleteLater);
    connect(thread, &QThread::finished, thread, &QObject::deleteLater);

    thread->start();
}

Любые предложения приветствуются.

Ответы [ 2 ]

2 голосов
/ 10 апреля 2019

Когда вы присваиваете новое значение std::shared_ptr - вы создаете новое общее значение, которое не имеет никакого отношения к предыдущему (вы можете взглянуть на счетчики обоих shared_ptrs).Вам следует изменить

fileToLoad = make_shared<string>(files.first().toUtf8().constData());

на

*fileToLoad  = files.first().toUtf8().constData()

(конечно, предварительно проверив, что fileToLoad не равен нулю)

0 голосов
/ 10 апреля 2019

Ваш код не будет работать, потому что в первой лямбде вы перезаписываете временный указатель внутри лямбды. Что вы можете сделать, это перезаписать std::string за указателем, и оно должно работать нормально:

auto fileToLoad = make_shared<string>();
    StartAsync(
        [=]()
    {

        QDir dir(dirPath.c_str());
        QString fileExtension(fileExt.c_str());

        for (int i = 0; i < 150; i++)
        {
            auto files = dir.entryList(QStringList() << fileExtension << fileExtension.toUpper(), QDir::Files);
            if (!files.empty())
            {
                //fileToLoad.reset(new string(files.first().toUtf8().constData()));
                *fileToLoad = files.first().toStdString();
                break;
            }

            this_thread::sleep_for(chrono::milliseconds(200));
        }
    },
        [=]()
    {
        if (fileToLoad == nullptr)
        {
            DisplayMessage("Timeout reached");
        }
        else
        {
            doFunc(*fileToLoad);
        }
    });
...