使用未来、承诺、分离线程时出现 C++ 错误 C2893、C2780、C2672
C++ Errors C2893, C2780, C2672 when using future, promise, detached thread
我有一个名为 cApp
的 class。
我想在后台 运行 CheckProcessList()
直到程序终止。所以我想,好吧,让 运行 它在一个分离的线程中,直到 ~cApp()
。我做了一个 bool 来跳出 CheckProcessList()
中的循环。在 ~cApp
中,我将 bool true m_bTerminateThread = true
设置为 break 并等待线程已结束执行的承诺 m_barrierFuture->wait()
。爆发后,我设定了线程现在结束执行的承诺 barrier.set_value()
。现在~cApp
可以完成执行了。或者至少这是我对我想要实现的目标以及如何实现的理解。好吧,不可能是对的,因为我收到编译器错误。
为什么首先要检查线程是否完成?因为程序在 运行 终止时中断,并且线程在 GetProcId()
的那一刻。如果程序在终止时正在休眠,则程序不会中断。
我在 msdn 和 Whosebug 上搜索了答案,但我没有从中得到任何我能理解的东西。我正在使用 VS2019 和 C++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
所有这些内存,因为 os 会处理它。
编辑2:
C2893: Failed to specialize function template
"unknown-type std::invoke(_Callable &&,_Ty1 &&,_Types2 &&...)
noexcept()".
C2780: "unknown-type std::invoke(_Callable &&) noexcept()":
expects 1 arguments - 2 provided
C2672: "invoke": no matching overloaded function found
m_tCheckProcList = new std::thread(&cApp::CheckProcessList, std::move(barrier));
我不知道你的错误属于哪一行(你没有显示)但我怀疑至少上面的说法是错误的。
如果您将线程过程的地址传递给 std::thread
构造函数并且此过程是非静态成员函数,则后面的下一个参数必须是您引用的对象的地址(毕竟是非-static 成员函数必须有一个 instance 代表调用它)。 std::promise
不是包含此类函数指针类型的类型 &cApp::CheckProcessList
因此这无法工作。
如果您想将该线程与创建它的对象相关联,通常此类调用如下所示:
std::thread(&cApp::CheckProcessList, this, ...
或者可以使用静态成员函数或自由函数。
cApp::CheckProcessList(std::promise<void> barrier)
代码中的另一个问题是将 promise 对象按值 传递给线程函数。这意味着承诺的本地副本,但承诺不可复制。
您也不能通过引用或指针传递它!因为 barrier
是 OnInit()
方法的局部变量,一旦该方法完成该变量就会被销毁 - 底层分离线程将乱用无效的堆栈帧或导致 未定义的行为 任何一种。也许您可以使 barrier
成为数据成员或重新考虑您的设计。
处理分离线程时要非常小心。如果使用不当,它们充满了陷阱。
我有一个名为 cApp
的 class。
我想在后台 运行 CheckProcessList()
直到程序终止。所以我想,好吧,让 运行 它在一个分离的线程中,直到 ~cApp()
。我做了一个 bool 来跳出 CheckProcessList()
中的循环。在 ~cApp
中,我将 bool true m_bTerminateThread = true
设置为 break 并等待线程已结束执行的承诺 m_barrierFuture->wait()
。爆发后,我设定了线程现在结束执行的承诺 barrier.set_value()
。现在~cApp
可以完成执行了。或者至少这是我对我想要实现的目标以及如何实现的理解。好吧,不可能是对的,因为我收到编译器错误。
为什么首先要检查线程是否完成?因为程序在 运行 终止时中断,并且线程在 GetProcId()
的那一刻。如果程序在终止时正在休眠,则程序不会中断。
我在 msdn 和 Whosebug 上搜索了答案,但我没有从中得到任何我能理解的东西。我正在使用 VS2019 和 C++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
所有这些内存,因为 os 会处理它。
编辑2:
C2893: Failed to specialize function template "unknown-type std::invoke(_Callable &&,_Ty1 &&,_Types2 &&...) noexcept()".
C2780: "unknown-type std::invoke(_Callable &&) noexcept()": expects 1 arguments - 2 provided
C2672: "invoke": no matching overloaded function found
m_tCheckProcList = new std::thread(&cApp::CheckProcessList, std::move(barrier));
我不知道你的错误属于哪一行(你没有显示)但我怀疑至少上面的说法是错误的。
如果您将线程过程的地址传递给 std::thread
构造函数并且此过程是非静态成员函数,则后面的下一个参数必须是您引用的对象的地址(毕竟是非-static 成员函数必须有一个 instance 代表调用它)。 std::promise
不是包含此类函数指针类型的类型 &cApp::CheckProcessList
因此这无法工作。
如果您想将该线程与创建它的对象相关联,通常此类调用如下所示:
std::thread(&cApp::CheckProcessList, this, ...
或者可以使用静态成员函数或自由函数。
cApp::CheckProcessList(std::promise<void> barrier)
代码中的另一个问题是将 promise 对象按值 传递给线程函数。这意味着承诺的本地副本,但承诺不可复制。
您也不能通过引用或指针传递它!因为 barrier
是 OnInit()
方法的局部变量,一旦该方法完成该变量就会被销毁 - 底层分离线程将乱用无效的堆栈帧或导致 未定义的行为 任何一种。也许您可以使 barrier
成为数据成员或重新考虑您的设计。
处理分离线程时要非常小心。如果使用不当,它们充满了陷阱。