[英]Passing thread routine multiple variables & stack size
在 web 的示例中,对CreateThread的调用通常会传递一个指向LPVOID lpParameter
结构的指针,然后您使用该指针来访问结构本身。
#include <Windows.h>
#include <stdio.h>
struct Point
{
float x,y,z ;
} ;
DWORD WINAPI threadStartPoint( LPVOID data )
{
Sleep( 1000 ) ;
Point *p = (Point*)data ;
printf( "%f %f %f\n", p->x, p->y, p->z ) ;
puts( "Thread job done" ) ;
return 0 ;
}
// From main
int main()
{
DWORD threadId ;
Point p ;
p.x=2, p.y=3, p.z=4 ;
HANDLE handle = CreateThread( 0, 0,
threadStartPoint,
(LPVOID)&p,
0, // ?? I think I should be using this parameter</b>
&threadId
) ;
if( !handle )
{
// Thread creation failed
puts( "start fail\n" );
}
else
{
printf( "started on threadid=%d\n", threadId ) ;
}
WaitForSingleObject( handle, 2000 ) ; // wait up to 2000 ms for the other thread to complete before moving on
puts( "main thread Exiting.." ) ;
//system( "pause" ) ;
}
我发现这有点不便,因为您必须确保 struct 存在,并确保在线程完成执行时正确销毁它。
我想启动我的线程,但是将普通堆栈 arguments即自动变量,或者可能是struct
本身传递给线程启动例程:
DWORD threadStartPointFuncStyleIWant( Data d ) ;
所以我的问题真的是:
DWORD validThreadFunc( LPVOID pParamStruct ) ;
DWORD threadFunc1( int p1, int p2 ) ; DWORD threadFunc2( Data d ) ;
CreateThread
仅接受一种类型的 function,即采用单个LPVOID
参数的类型。 无法与 kernel32.dll 通信,这是调用线程 function 的代码,它应该使用任何其他参数列表调用它。 kernel 总是以同样的方式调用 function。
你只需要像其他人一样继续这样做。 在堆上分配结构,将指针传递给线程例程,然后在从线程例程返回之前释放它。 也就是说,所有权从原始线程传递到新线程。 一旦新线程获得所有权,您可以使用像shared_ptr
这样的智能指针来确保它在您离开线程时被释放。
欢迎您在该结构中传递另一个 function 指针,或使用自己的方法传递 object。 然后,您的线程过程只不过是解包LPVOID
参数并分派到另一个 function 指针或方法,您可以在其中为线程执行所有实际工作。
做你想做的事,虽然并非不可能,但需要编译器和操作系统之间进行如此多的合作,以至于操作系统的设计目标会受到影响。
要创建线程,操作系统必须分配一个堆栈并对其进行初始化,以便堆栈帧的顶部看起来就像线程之前已经运行并被中断。 为了启动第一次执行的线程,操作系统然后执行中断返回,即。 操作系统永远不会调用线程,它们总是被返回。 为了提供可变的参数格式,操作系统需要知道参数块的长度,以便在推送中断帧之前将参数从调用线程堆栈复制到新线程的堆栈。 你看到这变得多么混乱了吗? 如果 ctor 线程和新线程有不同的调用约定会发生什么?
只传递一个可以在寄存器中“传递”的指针参数更容易/更安全。 对于像 C++ 这样的 OO 语言,这将是“this”,以便新线程可以访问它自己的数据成员和 vtable 指针。
Rgds,马丁
除了 boost::bind 调用之外,您还可以使用Boost线程库来获得您想要的东西:
#include <boost\thread.hpp>
struct Point
{
float x,y,z;
};
void threadStartPoint( Point p )
{
Sleep( 1000 ) ;
printf( "%f %f %f\n", p.x, p.y, p.z ) ;
}
int main(int argc, char** argv)
{
Point p;
p.x = 1;
p.y = 2;
p.z = 3;
// start the thread.
// first argument to "bind" is the worker thread function.
boost::thread t(boost::bind(threadStartPoint, p));
// wait for thread to exit
t.join();
return 0;
}
小心不要将源自堆栈的指针传递给生成线程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.