Потоки C 11 — запускают бесконечный рабочий поток изнутри класса

#c #multithreading #class #infinite

#c #многопоточность #класс #бесконечный

Вопрос:

я хочу предоставить класс, который содержит буфер при чтении некоторых данных (udp-пакетов или из файла). Все в порядке, если я запускаю свой поток из основного, но в этом случае я хочу избежать того, что пользователь должен настроить новый поток для себя.

итак, вот мой код настолько простой, насколько я мог его сделать:

 class DataCollector
{
    void startCollect()
    {
        std::thread t1(readSource);
    }

    bool readSource()
    {
        while(1)
        {
            // read some data for storage
        }
    }   
}

int main()
{
    DataCollector myDataCollector;
    myDataCollector.startCollect();

    while(1)
    {
        // do some other work, for example interpret the data
    }

    return 0;
}
 

теперь мне нужна ваша помощь. Как я могу вызвать этот поток внутри startCollect?

правка1: вот мой пример того, как это работает СЕЙЧАС!

 // ringbuffertest.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
//

#include "stdafx.h"
#include <thread>
#include <Windows.h>

class DataCollector
{
private:
    //std::thread collecterThread;

public:
    DataCollector(){}

    void startCollect()
    {       
        readSource();
    }

    bool readSource()
    {
        while (1)
        {
            printf("Hello from readSource!n");
            Sleep(1000);
        }
        return false;
    }
};


int _tmain(int argc, _TCHAR* argv[])
{
    DataCollector myDataCollector;

    std::thread t1(amp;DataCollector::startCollect, std::ref(myDataCollector));

    t1.join();
    return 0;
}
 

но, как я уже сказал, я хотел бы скрыть вызов потока внутри моей функции startCollect.

Комментарии:

1. Разве поток не должен быть свойством DataCollector? Затем вы можете создать его экземпляр в конструкторе и запустить его в startCollect .

2. Вам нужно будет иметь буфер (или два) и использовать condition_variable для уведомления каждого потока о том, что он предоставил некоторые данные.

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

Ответ №1:

Перед уничтожением активного thread объекта его необходимо либо присоединить (дождаться завершения потока, затем очистить его ресурсы), либо отсоединить (оставить для запуска и очистки после завершения).).

Таким образом, вы можете либо сделать поток переменной-членом, чтобы к нему можно было присоединиться позже:

 void startCollect()
{
    this->thread = std::thread(amp;DataCollector::readSource, this);
}

void waitForCollectToFinish()
{
    this->thread.join();
}
 

или вы можете отсоединить его, если вам не нужна возможность ждать его завершения, и иметь какой-либо другой способ сигнализации о том, что данные доступны:

 void startCollect()
{
    std::thread([this]{readSource();}).detach();
}
 

Вы также можете посмотреть на средства параллелизма более высокого уровня, такие как std::async и std::future . Это может быть удобнее, чем работать с потоками напрямую.

Комментарии:

1. Вы можете увидеть этот метод в действии на coliru .

2. this->thread = std::thread(readSource, this); выдает мне ошибки компилятора. я отредактирую рабочий пример (где я запускаю поток из main).

3. @user3783662: Вы правы, так и должно быть amp;DataCollection::readSource . Или, возможно, более читаемый, лямбда [this]{readSource();} .