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