Передача параметра в поток

257
14 марта 2018, 06:35

Есть класс. В поток есть возможность передать параметр. В примере ниже я туда передал строку и вывел ее в консоль. Но вот беда.. Мой экземпляр класса для потока не существует. То есть, я, конечно, могу создать еще один экземпляр класса в потоке и работать с ним, но хотелось бы как-то в поток передать тот экземпляр, с которым я работаю в main(). Необходимо иметь доступ к объектам класса и изменять их при определенных условиях. Например, из потока изменить значение bool checked и выполнить метод method1().

#include <windows.h>
#include <iostream>
#include <string>
using namespace std;
class SomeClass {
public:
    SomeClass(int value) {
        this->value = value;
        checked = false;
    }
    ~SomeClass() {
        cout << "The end" << endl;
    }
    void method1() {
        cout << value;
        checked = true;
    }
private:
    int value;
    bool checked;
};

DWORD WINAPI MyThread(LPVOID param) {
    cout << ((string*)param)[0] << endl;
    system("pause");
    return 0;
}
int main() {
    SomeClass SC(5);
    SC.method1();
    DWORD thID;
    HANDLE handle;
    string str = "hello";
    handle = CreateThread(NULL, NULL, MyThread, &str, NULL, &thID);
    system("pause");
    return 0;
}

Есть предположение, что вот так: (работает, но с тем же самым экземпляром я работаю?)

handle = CreateThread(NULL, NULL, MyThread, &SC, NULL, &thID);

и

DWORD WINAPI MyThread(LPVOID param) {
    SomeClass SC2 = ((SomeClass*)param)[0];
    SC2.method1();
    //cout << ((string*)param)[0] << endl;
    return 0;
}
Answer 1

Например, это можно сделать так:

#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
class SomeClass {
public:
    SomeClass(int value): m_value(value)
    {  }
    SomeClass(const SomeClass&) =  delete;
    int add(int v){
        m_mutex.lock(); // Тут лучше использовать lock_guard, но не буду усложнять
        int tmp = m_value;
        m_value += v;
        m_mutex.unlock();
        return tmp;
    }
    ~SomeClass() {
        std::cout << "~SomeClass" << std::endl;
    }
private:
    int m_value;
    std::mutex m_mutex;
};
int main()
{
    SomeClass foo(10);
    std::vector<std::thread> threads;
    for(std::size_t i = 0; i < 20; ++i){
        threads.emplace_back([&foo, i]{
            int addedValue = 1 << i;
            int oldValue = foo.add(addedValue);
            std::cout << "Поток " << i << " прибавил " << addedValue << " к " << oldValue << std::endl;
        });
    }
    for(auto& thread: threads){
       thread.join(); // Обязательно нужно дождатья завершения потоков
    }
    return 0;
}

У вас была правильная идея, но в строке SomeClass SC2 = ((SomeClass*)param)[0]; нет массива, нужно просто преобразовать void* в SomeClass* :

SomeClass* SC2 = reinterpret_cast<SomeClass*>(param);

Ну и о синхронизации нужно позаботиться, в моём примере это мьютекс, в winapi это критические секции.

READ ALSO
Понять лексер на конечном автомате

Понять лексер на конечном автомате

Привет!Хочу понять как сделать лекссер на C++Анализировал лексеры на Питон

202
Как обрабатывать labels в C++ (CLR)

Как обрабатывать labels в C++ (CLR)

Доброе время сутокТребуется изменять значения каждого Label`a через N время, каким образом можно организовать систему обращения к данным полям...

198
Вопрос по синтаксису использования make_uniuque

Вопрос по синтаксису использования make_uniuque

Подскажите, пожалуйста, как синтаксически верно переделать эту строчку:

185