代码之家  ›  专栏  ›  技术社区  ›  Jens Luedicke

如何将参数传递给线程对象?

  •  -1
  • Jens Luedicke  · 技术社区  · 16 年前

    我正在使用C++类库来提供一个线程基类,用户必须在其中使用 实施一 run() 方法。

    有没有推荐的方法来传递参数 () 方法?马上 我更喜欢通过构造函数传递它们(作为指针)。

    7 回复  |  直到 8 年前
        1
  •  2
  •   Andrei Vajna II    16 年前

    我不确定C++,但这就是Java中的方法。您将拥有一个扩展线程(或实现可运行)的类,以及一个具有您想要传递的参数的构造函数。然后,在创建新线程时,必须传递参数,然后启动线程,如下所示:

    Thread t = new MyThread(args...);
    t.start();
    

    你的情况一定是一样的。

        2
  •  1
  •   fa.    16 年前

    另一种方法是扩展这个线程类以接受一个函数作为唯一的构造函数参数,这样您就可以绑定其中的任何调用。

    那么使用线程的类不需要从线程继承,而只需要有一个(或多个)线程成员。该函数调用所需的任何起始点(类的某些方法具有任何参数)

        3
  •  1
  •   John Dibling    16 年前

    这是一个典型的模式:

    1)定义一个数据结构,它封装了线程所需的所有数据。 2)在主线程中,使用operator new在堆上实例化数据结构的副本。 3)填充数据结构,将指针强制转换为void*,通过线程库提供的任何方法将void*传递给线程过程。 4)当工作线程得到void*时,它将其重新解释为数据结构,然后获得对象的所有权。也就是说,当线程处理完数据后,线程会将其释放,而不是主线程将其释放。

    下面是您可以在Windows中编译和测试的示例代码。

        #include "stdafx.h"
        #include <windows.h>
        #include <process.h>
    
        struct ThreadData
        {
            HANDLE isRunning_;
        };
    
        DWORD WINAPI threadProc(void* v)
        {
    
        ThreadData* data = reinterpret_cast<ThreadData*>(v);
        if( !data )
            return 0;
    
        // tell the main thread that we are up & running
        SetEvent(data->isRunning_);
    
        // do your work here...
    
        return 1;
    }
    
    int main()
    {
        // must use heap-based allocation here so that we can transfer ownership
        // of this ThreadData object to the worker thread.  In other words, 
        // the threadProc() function will own & deallocate this resource when it's
        // done with it.
        ThreadData * data = new ThreadData;
        data->isRunning_ = CreateEvent(0, 1, 0, 0);
    
        // kick off the new thread, passing the thread data
        DWORD id = 0;
        HANDLE thread = CreateThread(0, 0, threadProc, reinterpret_cast<void*>(data), 0, &id);
    
        // wait for the worker thread to get up & running
        //
        // in real code, you need to check the return value from WFSO and handle it acordingly.  
        // Here I assume the retval is WAIT_OBJECT_0, indicating that the data->isRunning_ event 
        // has become signaled
        WaitForSingleObject(data->isRunning_,INFINITE); 
    
        // we're done, wait for the thread to die
        WaitForSingleObject(thread, INFINITE);
        CloseHandle(thread);
    
        return 0;
    
    }
    
        4
  •  0
  •   user82238    16 年前

    线程启动的一个常见问题是,传递的参数只存在于调用函数的堆栈上。线程启动通常被延迟,这样调用函数返回,而线程实际启动只需要一段时间——到那时参数就不存在了。

    解决方法之一是创建一个事件,然后启动线程,将事件作为参数之一传递。然后,启动函数等待事件,该事件在线程完成启动后由线程发出信号。

        5
  •  0
  •   MarkR    16 年前

    可以将参数作为线程类的成员传递。创建线程的线程可能会在线程启动之前调用其他方法和/或调用成员函数。因此,它可以填充工作所需的任何成员。然后,当调用run方法时,它将具有启动所需的信息。

    我假设您将为每个线程使用单独的对象。

    您通常会将创建的所有线程放入一个数组、向量等中。

        6
  •  0
  •   Carl Seleborg    16 年前

    可以通过构造函数传递它们。只要确保指针的寿命比线程长。

        7
  •  0
  •   cwap    16 年前

    好吧,我更愿意将参数放在start()方法中,这样您就可以有一个受保护的构造函数,而不必通过派生类构造函数级联参数。

    我很乐意让我的声明看起来像这样:

    class Thread
    {
    public:
       virtual void Start(int parameterCount, void *pars);
    protected:
       Thread();
       virtual void run(int parameterCount, void *pars) = 0;
    }
    

    只需确保您的参数以某种方式收缩,例如,1将为int,2将为double等。:)