Arhn - архитектура программирования

Базовый таймер с std::thread и std::chrono

Я пытаюсь реализовать базовый таймер с помощью классических методов: start() и stop(). Я использую С++ 11 с std::thread и std::chrono.

  • Метод запуска. Создает новый поток, который бездействует в течение заданного интервала времени, а затем выполняет указанную функцию std::function. Этот процесс повторяется до тех пор, пока установлен флаг «работает».
  • Метод остановки. Просто устанавливает флаг «работает» в false.

Я создал и запустил объект Timer, который показывает «Hello!» каждую секунду, затем другим потоком я пытаюсь остановить таймер, но не могу. Таймер никогда не останавливается.

Я думаю, что проблема связана с th.join()[*], который останавливает выполнение до тех пор, пока поток не завершится, но когда я удаляю строку th.join(), очевидно, программа завершается до того, как таймер начинает отсчет.

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

#include <iostream>
#include <thread>
#include <chrono>

using namespace std;

class Timer
{
    thread th;
    bool running = false;

public:
    typedef std::chrono::milliseconds Interval;
    typedef std::function<void(void)> Timeout;

    void start(const Interval &interval,
               const Timeout &timeout)
    {
        running = true;

        th = thread([=]()
        {
            while (running == true) {
                this_thread::sleep_for(interval);
                timeout();
            }
        });

// [*]
        th.join();
    }

    void stop()
    {
        running = false;
    }
};

int main(void)
{
    Timer tHello;
    tHello.start(chrono::milliseconds(1000),
                 []()
    {
        cout << "Hello!" << endl;
    });

    thread th([&]()
    {
        this_thread::sleep_for(chrono::seconds(2));
        tHello.stop();
    });

    th.join();

    return 0;
}

Выход:

Hello!
Hello!
...
...
...
Hello!

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

Ответы:


1

В Timer::start вы создаете новый поток в th, а затем сразу же join его с th.join(). По сути, start не вернется, пока этот порожденный поток не завершится. Конечно, он никогда не завершится, потому что ничто не установит значение false до тех пор, пока start не вернется...

Не join запускайте поток, пока не собираетесь дождаться его завершения. В этом случае в stop после установки running = false наверное самое правильное место.

Кроме того, хотя это и не является неправильным, нет необходимости создавать еще один поток в main для вызова this_thread::sleep_for. Вы можете просто сделать это с помощью основного потока:

int main()
{
    Timer tHello;
    tHello.start(chrono::milliseconds(1000), []{
        cout << "Hello!" << endl;
    });

    this_thread::sleep_for(chrono::seconds(2));
    tHello.stop();
}
03.02.2014

2

Вместо того, чтобы помещать join в start, поместите его после running = false в stop. Тогда метод остановки будет эффективно ждать завершения потока перед возвратом.

03.02.2014
Новые материалы

Коллекции публикаций по глубокому обучению
Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

Представляем: Pepita
Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

Советы по коду Laravel #2
1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

3 способа решить квадратное уравнение (3-й мой любимый) -
1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

Создание VR-миров с A-Frame
Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

Демистификация рекурсии
КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..