Ошибки C++ C2893, C2780, C2672 при использовании будущего, обещания, отдельного потока

У меня есть класс с именем cApp.

Я хочу работать в фоновом режиме, пока программа не завершится. Так что я подумал, хорошо, давайте запустим его в отдельном потоке, пока ~cApp(). Я сделал логическое значение, чтобы выйти из цикла CheckProcessList(). В я установил bool true m_bTerminateThread = trueвырваться и ждать обещания m_barrierFuture->wait()что поток завершил выполнение. После того, как я вырвался, я дал обещание barrier.set_value()что поток завершает выполнение. Теперь можно закончить выполнение. По крайней мере, таково мое понимание того, чего я хочу достичь и как это сделать. Ну, не может быть прав, так как я получаю ошибки компилятора.

Почему он хотел проверить, завершился ли поток в первую очередь? Поскольку программа прерывается во время выполнения, когда она завершается, а поток в этот момент находится в GetProcId(). Если он спит в момент завершения, программа не прерывается.

Я искал ответы в msdn и stackoverflow, но ничего не понял. Я использую VS2019 и С++14. Спасибо, ребята, заранее.

cApp.h

      #pragma once
#include "wx/wx.h"
#include "cMain.h"
#include <thread>
#include <future>

class cApp
    : public wxApp
{
public:
    cApp();
    ~cApp();

    virtual bool OnInit();

private:
    // supposed to run in a detached thread
    // until the program terminates
    void CheckProcessList(std::promise<void> barrier);

    // Checks whether or not the game processes are running
    // this thread runs asynchronous until ~cApp
    std::thread* m_tCheckProcList;
    // used in thread "m_tCheckProcList"
    // if set to true the thread terminates asap
    bool m_bTerminateThread;
    // used in thread "m_tCheckProcList"
    // in ~cApp this future waits for the promise that the thread has finished
    std::future<void>* m_barrierFuture;

    // Dark Souls 3 Processname
    const wchar_t* m_ds3Name;
    // Need for Speed: Most Wanted Processname
    const wchar_t* m_nfsmwName;
    // Serious Sam: The Second Encounter Processname
    const wchar_t* m_sstseName;

    const wxString* m_frameTitle;
    const wxSize* m_frameSize;

    cMain* m_mainFrame;
};

cApp.cpp

      #include "cApp.h"

wxIMPLEMENT_APP(cApp);

cApp::cApp()
{
    m_ds3Name = L"DarkSoulsIII.exe";
    m_sstseName = L"SeriousSam.exe";
    m_nfsmwName = L"speed.exe";
    m_frameTitle = new wxString("DeltaWin");
    m_frameSize = new wxSize(600, 450);
    m_bTerminateThread = false;
    m_mainFrame = nullptr;
    m_tCheckProcList = nullptr;
    m_barrierFuture = nullptr;
}

cApp::~cApp()
{
    // send the thread the "signal" to finish asap
    m_bTerminateThread = true;
    // wait for thread "m_tCheckProcList" to finish execution
    m_barrierFuture->wait();
}

bool cApp::OnInit()
{
    // create main top-level window
    m_mainFrame = new cMain(*m_frameTitle, wxDefaultPosition, *m_frameSize);
    m_mainFrame->Show();

    // create barrier and instantiate the future for it
    std::promise<void> barrier;
    m_barrierFuture = new std::future<void>(barrier.get_future());

    // start checking for running game processes in asynchronous thread
    m_tCheckProcList = new std::thread(&cApp::CheckProcessList, std::move(barrier));
    m_tCheckProcList->detach();

    return true;
}

void cApp::CheckProcessList(std::promise<void> barrier)
{   
    while (!m_bTerminateThread)
    {
        // Dark Souls 3
        if (GetProcId(m_ds3Name) == 0)
            m_mainFrame->MenuItemEnable(false, menuItem::DarkSouls3);
        else
            m_mainFrame->MenuItemEnable(true, menuItem::DarkSouls3);

        // Need for Speed: Most Wanted
        if (GetProcId(m_nfsmwName) == 0)
            m_mainFrame->MenuItemEnable(false, menuItem::NFSMostWanted);
        else
            m_mainFrame->MenuItemEnable(true, menuItem::NFSMostWanted);

        // Serious Sam: The Second Encounter
        if (GetProcId(m_sstseName) == 0)
            m_mainFrame->MenuItemEnable(false, menuItem::SeriousSamTSE);
        else
            m_mainFrame->MenuItemEnable(true, menuItem::SeriousSamTSE);

        // Sleep 1.5s to save resources
        std::this_thread::sleep_for(std::chrono::milliseconds(1500));
    }
    // set the promise that the thread has ended execution
    barrier.set_value();
}

редактировать: программа завершается после ~cApp. Поэтому я думаю, что в данном конкретном случае мне не нужно deleteвся эта память, потому что ОС заботится об этом.

редактировать2:

C2893: не удалось специализировать шаблон функции "unknown-type std::invoke(_Callable &&,_Ty1 &&,_Types2 &&...) noexcept()".

C2780: «неизвестный тип std::invoke(_Callable &&) noexcept()»: ожидается 1 аргумент — предоставлено 2

C2672: «вызвать»: не найдено подходящей перегруженной функции

1 ответ

m_tCheckProcList = new std::thread(&cApp::CheckProcessList, std::move(barrier));

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

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

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

      std::thread(&cApp::CheckProcessList, this, ...

Или можно использовать либо статическую функцию-член, либо бесплатную функцию.


cApp::CheckProcessList(std::promise<void> barrier)

Другая проблема в вашем коде — передача объекта обещания по значению в функцию потока. Это означает локальную копию обещания, но обещание нельзя скопировать. Вы также не можете передать его ни по ссылке, ни по указателю! потому что это локальная переменная метод, и как только этот метод завершает работу, эта переменная все равно уничтожается - базовый отсоединенный поток будет возиться с недопустимым фреймом стека или вызовет неопределенное поведение любого рода. Возможно, вы могли бы сделать элемент данных или переосмыслить свой дизайн.

Будьте очень осторожны при работе с отдельными потоками. Они полны подводных камней при неправильном использовании.

Другие вопросы по тегам