#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();}
.