如何将多个堆数组传递给新线程?

时间:2009-11-23 20:07:51

标签: c++ windows multithreading visual-c++

我正在尝试学习如何创建新线程并运行它们。我需要将一些变量传递给在新线程上运行的函数,但我无法找到如何将任何内容传递给新的函数/线程。

我正在关注http://www.devarticles.com/c/a/Cplusplus/Multithreading-in-C/1/,但它只涉及如何传递单个参数而没有其他内容。

附带问题,线程的工作方式与函数的工作方式完全相同,只是在不同的线程上,或者它是否比这更复杂?

谢谢,

-Faken

4 个答案:

答案 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;
}