在 C++11 中使用 std::thread 从两个 类 调用函数
Using std::thread to call functions from two Classes in C++11
我正在尝试实施一个 API 应该让用户并行创建两个通信渠道。一个通道使用 TCP,另一个使用 UDP。我有两个 classes 代表两个频道。这些 classes 实现了不同的功能。我想要并行从两个通道到 运行 的功能。为此,我使用 std::thread
创建两个线程,每个线程一个 (class)。
思路如下
头文件看起来像
class Channel_1
{
public:
int myfunc(int a, int b);
};
class Channel_2
{
public:
int anotherfunc(int a, int b);
};
在主cpp文件中
包含头文件
int main()
{
int a = 10, b = 20;
Channel_1 ch1;
Channel_2 ch2;
std::thread t(ch1.myfunc, a,b);
return 0;
}
我收到错误消息,指出不存在构造函数 std::thread
的实例。
我有以下问题。
- 我们不能在线程中调用 class 中的函数吗
构造函数?
- 这种使用线程从不同 class 调用函数的想法是否有意义?
你实际上有两个个问题:
语法错误。您需要传递一个指向成员函数的指针,如
std::thread t(&Channel_1::myfunc, a, b);
需要在 class 的实例上调用非静态成员函数。此实例必须作为第一个参数传递:
std::thread t(&Channel_1::myfunc, ch1, a, b);
正如一些程序员所说,您需要提供指向函数的指针(静态或非静态)。第三种选择可能是创建一个实现 start()
方法的基础 class,该方法使用此线程构造函数:
template< class Function, class... Args >
explicit thread( Function&& f, Args&&... args );
使用 lambda 的示例。这并不是一个完整的工作示例,它只是为了展示如何使用第三个线程构造函数 。
class thread_base {
private:
std::thread m_th;
bool m_terminated;
void proxy() {
// in the new thread
// add thread_base setup here if needed and
// call the execute() method in the derived class
execute();
}
public:
thread_base() : m_th(), m_terminated(false) {}
thread_base(const thread_base&) = delete;
thread_base& operator=(const thread_base&) = delete;
thread_base(thread_base&&) = default;
thread_base& operator=(thread_base&&) = default;
virtual ~thread_base() { join(); }
virtual void start() {
if(joinable()) throw std::runtime_error("thread already running");
else m_th = std::thread( [this] { proxy(); } );
}
inline bool joinable() { return m_th.joinable(); }
inline void join() { if(joinable()) { m_th.join(); m_terminated=false; } }
inline void terminate() { m_terminated=true; }
inline bool terminated() { return m_terminated; }
virtual void execute() = 0; // implement this in your derived classes
};
class Channel_1 : public thread_base {
void execute() {
// runs in a thread
// with a volontary check if a soft termination
// request has been issued
while( !terminated() ) {
// work
}
}
};
我正在尝试实施一个 API 应该让用户并行创建两个通信渠道。一个通道使用 TCP,另一个使用 UDP。我有两个 classes 代表两个频道。这些 classes 实现了不同的功能。我想要并行从两个通道到 运行 的功能。为此,我使用 std::thread
创建两个线程,每个线程一个 (class)。
思路如下
头文件看起来像
class Channel_1
{
public:
int myfunc(int a, int b);
};
class Channel_2
{
public:
int anotherfunc(int a, int b);
};
在主cpp文件中 包含头文件
int main()
{
int a = 10, b = 20;
Channel_1 ch1;
Channel_2 ch2;
std::thread t(ch1.myfunc, a,b);
return 0;
}
我收到错误消息,指出不存在构造函数 std::thread
的实例。
我有以下问题。
- 我们不能在线程中调用 class 中的函数吗 构造函数?
- 这种使用线程从不同 class 调用函数的想法是否有意义?
你实际上有两个个问题:
语法错误。您需要传递一个指向成员函数的指针,如
std::thread t(&Channel_1::myfunc, a, b);
需要在 class 的实例上调用非静态成员函数。此实例必须作为第一个参数传递:
std::thread t(&Channel_1::myfunc, ch1, a, b);
正如一些程序员所说,您需要提供指向函数的指针(静态或非静态)。第三种选择可能是创建一个实现 start()
方法的基础 class,该方法使用此线程构造函数:
template< class Function, class... Args >
explicit thread( Function&& f, Args&&... args );
使用 lambda 的示例。这并不是一个完整的工作示例,它只是为了展示如何使用第三个线程构造函数 。
class thread_base {
private:
std::thread m_th;
bool m_terminated;
void proxy() {
// in the new thread
// add thread_base setup here if needed and
// call the execute() method in the derived class
execute();
}
public:
thread_base() : m_th(), m_terminated(false) {}
thread_base(const thread_base&) = delete;
thread_base& operator=(const thread_base&) = delete;
thread_base(thread_base&&) = default;
thread_base& operator=(thread_base&&) = default;
virtual ~thread_base() { join(); }
virtual void start() {
if(joinable()) throw std::runtime_error("thread already running");
else m_th = std::thread( [this] { proxy(); } );
}
inline bool joinable() { return m_th.joinable(); }
inline void join() { if(joinable()) { m_th.join(); m_terminated=false; } }
inline void terminate() { m_terminated=true; }
inline bool terminated() { return m_terminated; }
virtual void execute() = 0; // implement this in your derived classes
};
class Channel_1 : public thread_base {
void execute() {
// runs in a thread
// with a volontary check if a soft termination
// request has been issued
while( !terminated() ) {
// work
}
}
};