Как передать параметры объекту Thread?

Я работаю с библиотекой классов С++, которая предоставляет базовый класс Thread, где пользователь должен внедрить метод run().

Есть ли рекомендуемый способ передачи параметров этому методу run()? Прямо сейчас Я предпочитаю передавать их через конструктор (в качестве указателей).

Ответ 1

Я не уверен в С++, но как вы это сделаете в Java. У вас будет класс, который расширяет Thread (или реализует Runnable) и конструктор с параметрами, которые вы хотите передать. Затем, когда вы создаете новый поток, вам нужно передать аргументы, а затем запустить поток, что-то вроде этого:

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

В вашем случае должно быть одинаково.

Ответ 2

Альтернативой является расширение этого класса Thread, чтобы принять функтор как только параметр конструктора, так что вы можете связать любой вызов внутри него.

Тогда класс, использующий потоки, не обязательно должен наследовать от Thread, но имеет только один (или более) элемент Thread. Функтор вызывает любую начальную точку, которую вы хотите (некоторый метод класса с любыми параметрами)

Ответ 3

Вот типичный шаблон:

1) Определите структуру данных, которая инкапсулирует все данные, необходимые вашему потоку 2) В основном потоке создайте копию структуры данных в куче, используя оператор new. 3) Заполните структуру данных, нарисуйте указатель на void *, передайте void * в процедуру потока любым способом, предоставленным вашей библиотекой потоков. 4) Когда рабочий поток получает пустоту *, он переинтерпретирует его в структуру данных и затем переходит в собственность объекта. Значение, когда поток выполняется с данными, поток освобождает его, в отличие от основного потока, освобождающего его.

Вот пример кода, который вы можете скомпилировать и протестировать в 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

Это нормально передать их через конструктор. Просто убедитесь, что указатели будут жить дольше, чем поток.

Ответ 5

Общей проблемой при запуске потока является то, что переданные аргументы существуют только в стеке в вызывающей функции. Запуск старта часто откладывается, так что вызывающая функция возвращается, и только через некоторое время поток фактически запускается - к тому моменту аргументы больше не существуют.

Одно из решений этого - создать событие, а затем запустить поток, передав событие как один из аргументов. Затем запускается функция запуска, которая сигнализируется потоком, когда он завершил запуск.

Ответ 6

Вы можете передать параметры как члены класса потока. Поток, который создает поток, может, предположительно, вызвать другие методы и/или вызвать функции-члены до начала потока. Поэтому он может заполнить все члены, необходимые для его работы. Затем, когда вызывается метод run, у него будет необходимая информация для запуска.

Я предполагаю, что вы будете использовать отдельный объект для каждого потока.

Обычно вы помещаете все созданные вами потоки в массив, вектор и т.д.

Ответ 7

Ну, я бы предпочел поместить параметры в метод Start(), чтобы вы могли иметь защищенный конструктор и не должны каскадировать параметры с помощью конструктора производных классов.

Я бы сказал, что мое объявление выглядит примерно так:

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

Просто убедитесь, что ваши параметры каким-то образом сжаты, например. # 1 будет int, # 2 будет двойным и т.д. И т.д.:)