首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >没有特定成员名称的c++ CreateThread非静态成员

没有特定成员名称的c++ CreateThread非静态成员
EN

Stack Overflow用户
提问于 2018-05-27 23:31:25
回答 3查看 363关注 0票数 0

我正在尝试创建一个包含非静态类成员的线程,如下所示:

代码语言:javascript
复制
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应用编程接口。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-06-10 04:06:31

最后,我用winapi替代std::thread,它的工作原理相同,而且可能更好。

代码语言:javascript
复制
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;
  }
};

也可以使用常用函数

代码语言:javascript
复制
void ltest(int i) {
   MessageBoxA(0, to_string(i).c_str(), 0, 0);
}
int main() {
   auto t = thread(ltest, 4);
   t.join();
}
票数 0
EN

Stack Overflow用户

发布于 2018-05-27 23:46:00

模板参数可以是pointer to member,因此您可以通过这种方式扩充StartThread,并使Thread::Thread的指向成员的指针参数成为模板参数。您不能向构造函数模板提供显式的模板参数,因此您必须使用特殊的“tag”参数来传达它们:

代码语言:javascript
复制
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();
}

请注意,成员类型为Tvoid()函数类型;在模板参数类型为auto的C++17中提供了更简单的语法。

或者,通过创建一个包含T*T::*的结构并将指向它的指针作为PVOID传递给它,将其保留为普通参数。这种方式的诀窍在于,您需要使用类型擦除来正确地销毁该块,或者使用reinterpret_cast将指针临时存储在固定类型下(就像对StartThread所做的那样)。

票数 1
EN

Stack Overflow用户

发布于 2018-05-28 01:25:19

如果不使用std::threadstd::function等C++运行时,您的选择就会受到一些限制。

尝试更多像这样的东西:

代码语言:javascript
复制
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();
}

否则,您可能不得不求助于更像这样的东西:

代码语言:javascript
复制
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();
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50553714

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档