我正在尝试学习如何创建新线程并运行它们。我需要将一些变量传递给在新线程上运行的函数,但我无法找到如何将任何内容传递给新的函数/线程。
我正在关注http://www.devarticles.com/c/a/Cplusplus/Multithreading-in-C/1/,但它只涉及如何传递单个参数而没有其他内容。
附带问题,线程的工作方式与函数的工作方式完全相同,只是在不同的线程上,或者它是否比这更复杂?
谢谢,
-Faken
答案 0 :(得分:4)
底层操作系统允许只将一个参数传递给线程CreateThread:
HANDLE WINAPI CreateThread(
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in SIZE_T dwStackSize,
__in LPTHREAD_START_ROUTINE lpStartAddress,
__in_opt LPVOID lpParameter,
__in DWORD dwCreationFlags,
__out_opt LPDWORD lpThreadId
);
因此,CRT线程创建函数也只允许一个参数,尽管名称为arglist
:
uintptr_t _beginthreadex(
void *security,
unsigned stack_size,
unsigned ( *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr
);
鉴于这些限制,通常的惯例是将指针传递给包含所有参数的结构/类。通常,使用C ++,可以创建一个静态函数,它将作为线程处理程序并将实例作为参数传递:
class Foo
{
int _someState;
int _otherState;
char _moreState[256];
unsigned DoWork();
static unsigned ThreadHandler(void*);
public:
void StartThread();
}
void Foo::StartThread()
{
_beginthreadex(..., Foo::ThreadHandler, this, ...);
}
unsigned Foo::ThreadHandler(void* arglist)
{
Foo* pFoo = (Foo*) arglist;
return pFoo->DoWork();
}
unsigned Foo::DoWork()
{
// do here all the thread work
}
这是一个相当常见的习惯用法,实际上它允许你根据需要向线程传递尽可能多的状态(=参数)。
答案 1 :(得分:2)
单个参数具有指针的大小。因此,您可以使用任意多的信息填充结构,并在创建新线程时将指针传递给此结构,就像将大型结构传递给函数一样。
关于线程执行,它的工作方式完全相同,但它与程序中的其他线程并行执行。因此,在访问线程中的全局变量时必须非常小心,因为它可能会被其他一些线程同时访问。
答案 2 :(得分:2)
boost::thread允许您创建具有多个参数的线程,如果您想要这样做的话。它是Windows线程API的替代品。
答案 3 :(得分:1)
我只想改写Remus Rusanu的回答。如果您传递一个参数,这意味着您可以传递任意数据的任意数据,正如许多人所指出的那样。只需将指针发送到结构,其中包含您要传递的内容。这很简单。我的建议有点C风格,而Remus Rusanu的C ++风格也许。
struct THREAD_DATA {
int data1;
struct MYSTRUCT data2;
...
};
void foo()
{
...
// It's important not to pass a stack-allocated local structure.
// That can be invalidated when this function exits.
// So, safely allocated with malloc/new.
THREAD_DATA* data = new THREAD_DATA;
data->data1 = // put the value you want to pass
data->data2 = //
_beginthreadex(..., ThreadWorkerFunc, data, ...);
}
unsigned int CALLBACK ThreadWorkerFunc(void* arg)
{
THREAD_DATA* data = (THREAD_DATA*)arg;
... = data->data1
delete data;
return 0;
}