c++线程函数中如何调用该方法下的外部函数?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++线程函数中如何调用该方法下的外部函数?相关的知识,希望对你有一定的参考价值。

我用c++
PVOID Mptr = (PVOID)service.start(beacon::get_heat_beat_time());
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Mptr, NULL, NULL, &dwThreadId);
WaitForSingleObject(hThread, INFINITE);
在start这个方法中我还去执行了其他类里面的其他方法
程序是可以编译通过的 但是执行调试就会遇到空指针错误
start方法中我调用了好多个其他类里面的方法
因为我不太了解线程机制 也是初学者 目前不知道有没有一个很好的方法

需要定位一下在哪里提示空指针错误:
个人觉得CreateThread函数可能会有错误,按你的代码理解mPtr应该是一个start返回的回调函数地址,如果不是肯定会错。
另外应该在CreateThread函数前判断返回的mptr指针是否为空,也许start函数失败呢,没有返回正确的函数地址也是会错的。
参考技术A 强制类型转换基本上可以掩盖一切编译错误,除非你非常懂转换结果的兼容性,就不要用强制类型转换
PVOID Mptr = (PVOID)service.start(beacon::get_heat_beat_time());
这个赋值成立么?service.start返回的是一个合法的函数指针么?注意Mptr指向的是后面这个函数调用的返回值,不是把后面整体当成一个函数给它追问

事情是这样的 我用的vs2019创建的控制台程序 然后程序必须加上getchar函数一直保持这个窗口才可以执行正常的功能 因为控制台程序的特性 执行完就关闭了 我尝试用while死循环 但是那样会一直消耗cpu资源 我想着创建线程来执行start方法 但是一直失败 就出现了 我上面的问题

我的需求是不依赖getchar函数   而且这个黑框很烦人 最好能修改子系统隐藏,但getchar就失效了

追答

首先这不适合用控制台程序!你应该用Windows Service或者MFC Application。不过这两者都需要你很长时间的学习
其次:这个问题的本身在于你那个函数指针是否正确,感觉你完全把下面这个当作可以晚点执行的函数了!这不是,这是一个普通的立刻执行的表达式。
(PVOID)service.start(beacon::get_heat_beat_time());
可惜我没法给你更多的指导,你需要解决的问题可能需要你学习几年的事情。才开始学习不建议搞这么复杂的设计

追问

非常感谢您提的宝贵建议 我会多去实践学习寻找解决问题的办法 并且多总结经验

本回答被提问者采纳

c++多线程在异常环境下的等待

      c++11开始支持多线程编程,相关的类和函数封装在标准库头文件<thread>中,而c++多线程编程很重要的一点就是当用户创建一个std::thread对象,关联了可调用对象后,需要在该thread对象销毁前调用join()或detach()。其中join()函数用于结合线程,确保在创建该thread对象的函数退出前,该线程执行完毕;而detach()函数则表示分离线程,即让线程在后台运行,线程的所有权和控制权交给c++运行时库。若thread对象销毁前没有调用join()或detach(),则程序会被终止(thread的析构函数调用std::terminate() )。

      如果用户要分离线程,那么一般情况下在线程启动后立即调用detach()即可。但若需要等待线程,那么调用join()的时机就很重要:如果线程在开始之后、调用join()之前发生了异常,则join()的调用就会被跳过。保证线程在异常环境下的等待的方法之一是使用try/catch语句块:

 1 #include <thread>
 2 #include <stdexcept>
 3 
 4 using std::thread;
 5 using std::runtime_error;
 6 
 7 void func();
 8 
 9 void TestThread() {
10     thread thrd(func);
11     try
12     {
13         //...
14     }
15     catch (runtime_error re)
16     {
17         thrd.join();
18         throw re;
19     }
20     thrd.join();
21 }

      但是很显然,使用try/catch语句块很罗嗦,且容易将作用域弄乱。一个更好的方法是使用资源获取即初始化(Resource Acquisition Is Initialization, RAII)的方法,RAII是C++的一种管理资源、避免泄漏的惯用法。C++标准保证任何情况下,已构造的对象最终会销毁,即它的析构函数最终会被调用。简单的说,RAII 的做法是使用一个对象,在其构造时获取资源,在对象生命期控制对资源的访问使之始终保持有效,最后在对象析构的时候释放资源。

      使用RAII的代码如下:

 1 #include <thread>
 2 
 3 using std::thread;
 4 
 5 void func();
 6 
 7 class Thread_RAII {
 8 private:
 9     thread &thrd;
10 public:
11     explicit Thread_RAII(thread &p_thrd) : thrd(p_thrd) {}
12     ~Thread_RAII()
13     {
14         if (thrd.joinable())
15         {
16             thrd.join();
17         }
18     }
19     Thread_RAII(const Thread_RAII &) = delete;
20     Thread_RAII & operator=(const Thread_RAII &) = delete;
21 };
22 
23 void TestThread()
24 {
25     thread thrd(func);
26     Thread_RAII tr(thrd);
27     //...
28 }

      当函数TestThread()执行到末尾时,局部对象按照构造的逆序进行销毁,因此tr首先被销毁,于是其中的thrd对象被结合,即使在之前其中的某条语句执行时引发异常而退出时也是如此。

      上述代码还有两点需要注意:

      ①析构函数在调用join()之前需要检查thrd是否是joinable()的,因为对于一个线程,join()只能调用一次。

      ②Thread_RAII类的拷贝构造函数及拷贝复制运算符是删除的,这是因为thread对象和istream、ostream、unique_ptr一样是不可拷贝的(但可以移动)。

以上是关于c++线程函数中如何调用该方法下的外部函数?的主要内容,如果未能解决你的问题,请参考以下文章

Visual Lisp:如何调用外部 C++ DLL 中的函数

在C ++中,是否有任何理由产生并立即加入一个线程,而不是直接调用该函数?

如何调用Angular组件中assets文件夹下的单独文件中的外部Javascript函数?

QT C++,如何在在一个CPP里直接调用到另一个CPP里的函数

如何从外部调用的 Python 函数在 Qlabel 中显示消息

在 MFC 中实现多线程以更新外部函数可访问的内部字典