【问题标题】:How do I pass multiple heap arrays to a new thread?如何将多个堆数组传递给新线程?
【发布时间】:2009-11-23 20:07:51
【问题描述】:

我正在尝试学习如何创建新线程并运行它们。我需要将一些变量传递给在新线程上运行的函数,但我不知道如何将任何东西实际传递给该新函数/线程。

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

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

谢谢,

-伪造

【问题讨论】:

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


    【解决方案1】:

    底层操作系统只允许将一个参数传递给线程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
    }
    

    这是一个相当常见的习惯用法,实际上它允许您根据需要向线程传递尽可能多的状态(=参数)。

    【讨论】:

      【解决方案2】:

      单个参数具有指针的大小。因此,您可以用尽可能多的信息填充结构,并在创建新线程时传递指向该结构的指针,就像将大结构传递给函数一样。

      关于线程执行,它的工作原理完全相同,但它与程序中的其他线程并行执行。因此,在访问线程中的全局变量时必须非常小心,因为它可能会同时被其他线程访问。

      【讨论】:

      • 所以这意味着我不能像普通函数一样干净地将一些数组传递到一个新线程中?我需要将一个指针传递给一个结构,然后该结构将包含指向我的堆数组的指针?有没有更简单更直接的方法?
      • 这几乎就是你必须这样做的方式。无论如何,与线程的其他噩梦相比,它并没有那么糟糕。 ;)
      • 我想不出更简单的方法(但请记住,数组实际上是指向其第一个元素的指针,所以不要使结构过于复杂)
      • 嗯...是时候学习如何正确使用结构了...结构中可以有结构吗?如果不是这样,事情就会变得一团糟……实际上无论哪种方式都会变得一团糟。
      • 是的,你可以在一个结构里面有一个结构,并且可以嵌套任意深度的结构/类/联合。
      【解决方案3】:

      boost::thread 允许您创建具有多个参数的线程,如果您想尝试一下的话。它是 Windows 线程 API 的替代方案。

      【讨论】:

        【解决方案4】:

        我将重新表述 Remus Rusanu 的回答。正如许多人指出的那样,如果您传递一个参数,这意味着您可以传递任意大小的任何数据。只需将 pointer 发送到包含您要传递的内容的 结构。这真的很简单。我的建议有点 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;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-06-08
          • 1970-01-01
          • 2012-01-03
          • 2021-07-08
          • 2020-12-04
          相关资源
          最近更新 更多