我正在尝试创建一个包含非静态类成员的线程,如下所示:
template <class clName>
DWORD WINAPI StartThread(PVOID ptr) {
((clName*)(ptr))->testf(); // this is static member name I want to be able use different names with the same function
return 1;
}
class Thread {
private :
HANDLE native_handle = 0;
DWORD id = 0;
public :
template <class T,class U>
Thread(T U::*member,U* original); // I want to use different members with the same function
bool run();
}
template<class T,class U>
Thread::Thread(T U::*member, U* original)
{
native_handle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)StartThread<U>,original, CREATE_SUSPENDED, &id);
}
bool Thread::run() {
DWORD res = ResumeThread(native_handle);
if (res == (DWORD)-1) return false;
return true;
}
class testt {
public :
void testf() {
MessageBoxA(0, "working", "", 0);
}
void doIt() {
Thread t(&testt::testf,this);
t.run();
}
};
int main() {
testt tt;
tt.doIt();
}
如你所见,我只能运行一个特定的成员,所以这个方法是不可移植的,不能用于任何类或成员。
我知道我可以很容易地使用std::thread
,但我正在处理一个不应该使用任何C++运行时的项目,所以我为new
/delete
、线程、文件I/O等创建包装器。否则,我总是使用std::thread
,它非常棒。在这个项目中,我只能使用Win32应用编程接口。
发布于 2018-06-10 04:06:31
最后,我用winapi替代std::thread,它的工作原理相同,而且可能更好。
class letTest {
private :
void pri(int u,float g, char l) {
MessageBoxA(0, 0, 0, 0);
}
public :
int doIt(int o) {
auto t = thread(&letTest::pri, this,5,4.2,'k'); // works well with any number and type of parameters
t.join();
return 5;
}
};
也可以使用常用函数
void ltest(int i) {
MessageBoxA(0, to_string(i).c_str(), 0, 0);
}
int main() {
auto t = thread(ltest, 4);
t.join();
}
发布于 2018-05-27 23:46:00
模板参数可以是pointer to member,因此您可以通过这种方式扩充StartThread
,并使Thread::Thread
的指向成员的指针参数成为模板参数。您不能向构造函数模板提供显式的模板参数,因此您必须使用特殊的“tag”参数来传达它们:
template<class C,class T,T C::*P>
DWORD WINAPI StartThread(PVOID ptr) {
(static_cast<C*>(ptr)->*P)();
return 1;
}
template<class C,class T,T C::*P>
struct Tag {};
class Thread {
private :
HANDLE native_handle = 0;
DWORD id = 0;
public :
template<class C,class T,T C::*P>
Thread(Tag<C,T,P>,C*);
bool run();
};
template<class C,class T,T C::*P>
Thread::Thread(Tag<C,T,P>,C* original)
{
native_handle = CreateThread(0, 0, StartThread<C,T,P>,original,
CREATE_SUSPENDED, &id);
}
bool Thread::run() {
DWORD res = ResumeThread(native_handle);
if (res == (DWORD)-1) return false;
return true;
}
class testt {
public :
void testf() {
MessageBoxA(0, "working", "", 0);
}
void doIt() {
Thread t(Tag<testt,void(),&testt::testf>(),this);
t.run();
}
};
int main() {
testt tt;
tt.doIt();
}
请注意,成员类型为T
的void()
函数类型;在模板参数类型为auto
的C++17中提供了更简单的语法。
或者,通过创建一个包含T*
和T::*
的结构并将指向它的指针作为PVOID
传递给它,将其保留为普通参数。这种方式的诀窍在于,您需要使用类型擦除来正确地销毁该块,或者使用reinterpret_cast
将指针临时存储在固定类型下(就像对StartThread
所做的那样)。
发布于 2018-05-28 01:25:19
如果不使用std::thread
和std::function
等C++运行时,您的选择就会受到一些限制。
尝试更多像这样的东西:
template <class U>
class Thread {
private:
HANDLE native_handle = 0;
DWORD id = 0;
U *object;
void (U::*object_member)();
static DWORD WINAPI ThreadProc(PVOID ptr);
public:
Thread(void U::*member, U* obj);
bool start();
};
template<class U>
DWORD WINAPI Thread<U>::ThreadProc(PVOID ptr) {
Thread *t = static_cast<Thread*>(ptr);
U *obj = t->object;
void (U::*member)() = t->object_member;
(obj->*member)();
return 1;
}
template<class U>
Thread<U>::Thread(void U::*member, U* obj) :
object_member(member), object(obj) {
native_handle = CreateThread(0, 0, &ThreadProc, this, CREATE_SUSPENDED, &id);
}
template <class U>
bool Thread<U>::start() {
return (ResumeThread(native_handle) != (DWORD)-1);
}
class testt {
public:
void testf() {
MessageBoxA(0, "working", "", 0);
}
void doIt() {
Thread<testt> t(&testt::testf, this);
t.start();
}
};
int main() {
testt tt;
tt.doIt();
}
否则,您可能不得不求助于更像这样的东西:
class Thread {
private:
HANDLE native_handle = 0;
DWORD id = 0;
void (*func)(void*);
void *param;
static DWORD WINAPI ThreadProc(PVOID ptr);
public:
Thread(void (*f)(void*), void* p);
bool start();
};
DWORD WINAPI Thread::ThreadProc(PVOID ptr) {
Thread *t = static_cast<Thread*>(ptr);
void (*func)(void*) = t->func;
(*func)(t->param);
return 1;
}
Thread::Thread(void (*f)(void*), void *p) :
func(f), param(p) {
native_handle = CreateThread(0, 0, &ThreadProc, this, CREATE_SUSPENDED, &id);
}
bool Thread::start() {
return (ResumeThread(native_handle) != (DWORD)-1);
}
class testt {
private:
static void proc(void *p) {
static_cast<testt*>(p)->testf();
}
public:
void testf() {
MessageBoxA(0, "working", "", 0);
}
void doIt() {
Thread t(&testt::proc, this);
t.start();
}
};
int main() {
testt tt;
tt.doIt();
}
https://stackoverflow.com/questions/50553714
复制相似问题