我有一个类,它有一个需要连续运行的方法,但也能够从用户接收输入。所以我想我会使用一个线程单独运行该方法。
代码看起来像这样(只是主干):
class SystemManager
{
private:
int command;
bool commandAcK;
bool running;
//other vars
public:
SystemManager()
{
//initialisation
}
void runningAlgorithm()
{
while (running)
{
if (commandAcK)
{
//solve command
}
//run algorithm
//print results
}
}
void readCmd()
{
cin >> command;
commandAcK = true;
}
};
int main()
{
SystemManager *SM = new SystemManager;
thread tRunning = SM->runningAlgorithm();
}
现在错误看起来像这样:
没有合适的构造函数可以转换为" void
"到" std::thread
"
错误C2440'初始化':无法转换为' void'到' std :: thread'
我找到了一种新方法,并没有给我任何错误
std::thread tRunning(&SystemManager::runningAlgorithm, SystemManager());
我不明白的是,这种方法并不仅仅使用泛型函数的类实例。如何将其链接到特定实例?我需要它,所以它可以读取变量的值。
其次,SystemManager前面的"&"
是做什么的?
(&SystemManager::runningAlgorithm)
第三是有更好的方法吗?你有什么想法吗?
提前谢谢。
答案 0 :(得分:2)
std::thread tRunning(&SystemManager::runningAlgorithm, SystemManager());
确实使用了您班级的实例。它使用的实例是SystemManager()
,它是一个临时的,只对线程可用。如果你需要共享实例,那么你需要自己创建一个实例并通过引用传递它,如
SystemManager sys_manager;
std::thread tRunning([&](){sys_manager.runningAlgorithm();});
现在您的呼叫站点和您的线程具有相同的实例。
另请注意,command
和commandAck
需要通过某种同步进行保护,因为您可以在阅读时写入data race并随后undefined behavior。使用std::atmoic
应该适合您。
答案 1 :(得分:1)
operator()
的构造函数接受仿函数,并可选择接受它的参数。仿函数就是任何可以被称为"使用std::thread tRunning(&SystemManager::runningAlgorithm, SystemManager());
。
然后它启动一个线程,在该线程内部调用你的函子。
SystemManager::runningAlgorithm
这将调用成员函数this
,传入唯一的参数SystemManager()
(this
创建一个临时实例)。
请记住,成员函数始终接受&SystemManager::runningAlgorithm
作为第一个参数。
runningAlgorithm
从类SystemManager
返回成员函数std::thread tRunning([]{ SystemManager().runningAlgorithm(); });
的地址。
在现代C ++中,这个代码可以用lambda简化(即更易读):
A
答案 2 :(得分:1)
该行
thread tRunning = SM->runningAlgorithm();
获取运行SM->runningAlgorithm()
(void
)的结果,并尝试从中构造一个线程。但是,如果你看一下the relevant constructor,你可以看到它需要一个类似函数的参数(带有可能的参数)。
运行它的一种方法是通过lambda函数:
thread tRunning(
[SM](){SM->runningAlgorithm();});
另外两件事需要注意:
你应该在调用析构函数之前加入线程,在这种情况下:
tRunning.join();
你有一个(短暂的)内存泄漏。为什么不在堆栈上创建它呢?
SystemManager SM;
thread tRunning(
[&](){SM.runningAlgorithm();});
tRunning.join();
答案 3 :(得分:1)
嗯......我想你在进行多线程之前需要学习一些c ++的基本概念。
然而......在你的代码中,
thread tRunning = SM->runningAlgorithm();
尝试将函数的结果(即void ...)放在thread类型的变量中......非常可能是正确的。
相反,你的第二个代码有两个参数:
std::thread tRunning(
&SystemManager::runningAlgorithm, //a pointer to a method (a pointer to the code of your function, and that is why you use the "&", even though you could have left that out)
SystemManager()); // An instance of the value, built on the stack.
我很高兴您对“新”这个词的缺乏感到困惑(来自更高级别的语言?),但这就是它的工作原理:
SystemManager sm = SystemManager(); // <- variable created on the stack, will be automatically destroyed when out of scope
SystemManager *psm = new SystemManager(); // Created in the heap, while in the stack remains just a pointer to it.
//You will need to delete it when done with :
delete psm;
回答问题
如何将其链接到特定实例?我需要它,所以它可以读取变量的值。
你可以这样做:
int main()
{
SystemManager SM; // = SystemManager(); // <- this is not needed
std::thread tRunning(SystemManager::runningAlgorithm, SM);
// Access SM as you need
// REMEMBER TO CLOSE & JOIN THE THREAD!
tRunning.join();
}
我仍然认为你应该首先习惯潜在的概念,否则将很难继续。