Мне нужна функция потока, чтобы печатать случайное число каждые 2 секунды, не останавливая реальную программу - PullRequest
0 голосов
/ 30 октября 2019
vector < component * > v;
void add(int type, int id, string name) {
    //creating object and pushing into the vector
}

void display()
//display the values
void thred1(int id) {
    bool err = false;
    for (size_t i = 0; i < v.size(); i++) {
        if (id == v[i] - > id) {
            cout << "element found " << v[i] - > id << " -- " << v[i] - > name << endl;
            v[i] - > Read();
            this_thread::sleep_for(chrono::seconds(2));
            err = true;
            break;

        } else
            cout << "NOT FOUND" << endl;
    }
}
int main() {
    int choose;
    int type;
    int id;
    string name;
    int sec;
    do {
        cout << "1.ADD A COMPONENT" << endl;
        cout << "2.DISPLAY A COMPONENT" << endl;
        cout << "3.START MONITORING" << endl;
        cout << "4.STOP MONITORING" << endl;
        cout << "5.QUIT" << endl;
        cin >> choose;
        switch (choose) {
        case 1:
            //adding component  
        case 2:
            {
                display();
                break;
            }
        case 3:
            {
                int id;
                cout << "ID to be monitored" << endl;;
                cin >> id;
                thread the1(thred1, id);
                the1.join();
                break;
            }
        case 4:
            {
                cout << "monitoring stopped" << endl;
                break;
            }
        }
        if (choose == 5)
            break;
    } while (true);
}

Когда поток выполняется, он печатает случайное число только один раз, мне нужно печатать его каждые 2 секунды. Например: если выбрана опция мониторинга, значения должны быть напечатаны до нажатия кнопки «Остановить мониторинг». Между тем мне нужно добавить компонент или отобразить его во время печати. ​​

Ответы [ 2 ]

3 голосов
/ 30 октября 2019

Хорошо, ваш код не имеет смысла, но многопоточность может сбивать с толку при первом запуске.

Вы делаете это:

    case 3:
        {
            int id;
            cout << "ID to be monitored" << endl;;
            cin >> id;
            thread the1(thred1, id);
            the1.join();
            break;
        }

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

Но это то, что делает the1.join () - этоблокирует основной поток выполнения до завершения рабочего потока. Это то, что вы хотите?

Далее, ваш рабочий поток довольно прост. Он ищет ваш вектор, останавливаясь на 1 секунду для каждого цикла. Это НЕ делает какой-либо работы навсегда. Он просто проходит через ваш вектор, ища значение, которое вы передали. Это то, что вы хотите?

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

Сохранение вашего кода в основном нетронутым ...

В главном потоке я объявил бы переменную.

thread * myThread = nullptr;

Я также объявил бы глобальную переменную с именем stopThread:

bool stopThread = false;

Для случая 3 я бы переписал его как:

case 3: {int id;cout << "ID для мониторинга" << endl ;;cin >> id;// Это убивает старый поток в случае, если они делают вариант 3 дважды. if (myThread! = nullptr) {stopThread = true;myThread-> Join ();удалить myThread;} stopThread = false;myThread = новая тема (thred1, id);сломать;}

Для случая 4:

case 4:
   if (myThread != nullptr) {
       stopThread = true;
       myThread.join();
       delete myThread;
       myThread = nullptr;
       cout << "monitoring stopped" << endl;
    }
    break;

Тогда вы в своем методе потока:

void thred1(int id) {
    while (!stopThread) {
        bool err = false;
        for (size_t i = 0; !stopThread && i < v.size(); i++) {
            if (id == v[i] - > id) {
                c.   out << "element found " << v[i] - > id << " -- " << v[i] - > name << endl;
                v[i] - > Read();
                this_thread::sleep_for(chrono::seconds(2));
                err = true;
                break;
            }
        }
    }
}

Теперь вот что я сделал ... Сначала я настроилтак что ваша тема длится, что я думаю, что вы хотите. Я дал вам средство сообщить потоку об остановке (переменная stopThread). И ваш поток теперь зацикливается, пока вы не скажете ему выйти.

Это не точно , как я бы написал, но это близко к тому, что я сделал бы, внося минимальные изменения в вашкод.

0 голосов
/ 07 ноября 2019

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

Вот мое решението, что я интерпретирую как вашу проблему.

Есть несколько моментов (надеюсь), представляющих интерес:

  1. Поток инкапсулирован в компоненте
  2. реализация компонента, время жизнии объекты дескриптора разрабатываются по принципу 1-class-1-job
  3. межпотоковая последовательность учитывается при управлении активностью компонента
  4. мьютекс вокруг использования std::cout контролируемогочерез шаблон функции emit().
  5. чистое отключение

Код предлагается как есть. Проверено на MacOS. Будут ошибки. Всегда есть в первом срезе многопоточный код.

//
//  main.cpp
//  so-58625693
//

#include <ciso646>
#include <vector>
#include <iostream>
#include <memory>
#include <string>
#include <sstream>
#include <cassert>
#include <thread>
#include <condition_variable>
#include <chrono>

std::mutex emit_mutex;

template<class...Ts>
void emit(Ts&&...ts)
{
    auto lock = std::unique_lock<std::mutex>(emit_mutex);
    int x[] = {
        0,
        (std::cout << ts, 0)...
    };
    (void) x;
}

// implements the workings of a component
class component_impl : public std::enable_shared_from_this<component_impl>
{
    using mutex_type = std::mutex;
    using lock_type = std::unique_lock<mutex_type>;

    enum state_type
    {
        stopped,
        started,
        stopping
    };

    template<class F>
    auto sync(F f) const
    {
        return f(lock_type(mutex_));
    }

public:

    component_impl(int type, int id, std::string name)
    : type_(type), id_(id), name_(std::move(name))
    {}

    auto start() -> void
    {
        sync([&](auto&& lock){
            switch(state_)
            {
                case stopped:
                    handle_start(lock);
                    break;

                case started:
                case stopping:
                    emit(identity(), " is already started\n");
                    break;
            }
        });
    }

    bool stop() {
        auto did_stop = sync([&](auto&& lock){
            switch(state_)
            {
                case stopping:
                case stopped:
                    return false;

                case started:
                    state_ = stopping;
                    stop_condition_.notify_one();
                    emit(identity(), " stop requested\n");
                    return true;
            }
            return false;
        });

        if (did_stop and thread_.joinable())
            thread_.join();

        return did_stop;
    }

    void display() const
    {
        identify(std::cout);
        std::cout << '\n';
    }

    void identify(std::ostream& os) const
    {
        os << type_ << " : " << id_ << " : " << name_;
    }

    auto identity() const -> std::string
    {
        std::ostringstream ss;
        identify(ss);
        return ss.str();
    }

    auto id() const -> int {
        return id_;
    }

private:

    auto run() -> void
    {
        using namespace std::literals;

        auto lock = lock_type(mutex_);
        for(;;)
        {
            auto stop = stop_condition_.wait_for(lock, 2s, [&] { return state_ != started; });
            if (stop)
            {
                state_ = stopped;
                break;
            }
            else
            {
                lock.unlock();
                emit(identity(), " sampling\n");
                lock.lock();
            }
        }
    }

    // precondition: mutex is locked
    // precondition: not started
    auto handle_start(lock_type const& lock) -> void
    {
        assert(lock.owns_lock());
        assert(state_ == stopped);

        thread_ = std::thread([self = this->shared_from_this()]
        {
            self->run();
        });

        state_ = started;
    }


    // invariants

    const int type_, id_;
    const std::string name_;

    // control
    mutable mutex_type mutex_;
    std::condition_variable stop_condition_;
    std::thread thread_;

    // mutable state
    state_type state_ = stopped;
};

struct component_lifetime
{
    component_lifetime(std::unique_ptr<component_impl> impl)
    : impl_(std::move(impl))
    {
    }

    ~component_lifetime()
    {
        impl_->stop();
    }

    auto impl() -> component_impl&
    {
        return *impl_;
    }

private:
    std::shared_ptr<component_impl> impl_;
};

// manages the lifetime of a component
struct component
{
    component(int type, int id, std::string name)
    : impl_(construct_lifetime(type, id, std::move(name)))
    {
    }

    component_lifetime& lifetime() { return *impl_; }
    component_lifetime& lifetime() const { return *impl_; }

    component_impl& impl() { return lifetime().impl(); }
    component_impl& impl() const { return lifetime().impl(); }


    void start()
    {
        impl().start();
    }


    int id() const {
        return impl().id();
    }

    void display() const
    {
        impl().display();
    }

    bool stop()
    {
        return impl().stop();
    }


private:

    static auto construct_impl(int type, int id, std::string name) -> std::unique_ptr<component_impl>
    {
        return std::make_unique<component_impl>(type, id, std::move(name));
    }

    static auto construct_lifetime(int type, int id, std::string name) -> std::shared_ptr<component_lifetime>
    {
        auto impl = construct_impl(type, id, std::move(name));
        auto lifetime = std::make_shared<component_lifetime>(std::move(impl));
        return lifetime;
    }


    std::shared_ptr<component_lifetime> impl_;
};


struct component_set
{
    component_set() = default;
    component_set(component_set const&) = delete;
    component_set& operator=(component_set const&) = delete;
    ~component_set()
    {
        shutdown();
    }

    void add(int type, int id, std::string name) {
        auto lock = std::unique_lock<std::mutex>(m_);
        v_.emplace_back(type, id, std::move(name));
    }

    auto locate(int id) -> component*
    {
        auto match_id = [id](component const& c)
        {
            return c.id() == id;
        };

        auto i = std::find_if(std::begin(v_), std::end(v_), match_id);

        if (i != std::end(v_))
            return std::addressof(*i);
        else
            return nullptr;
    }

    void start(int id)
    {
        auto pc = locate(id);
        if (pc)
            pc->start();
        else
            emit("id ", id, " not found\n");
    }

    void stop(int id)
    {
        auto pc = locate(id);
        if (pc)
        {
            if (not pc->stop())
            {
                emit("id ", id, " was not running");
            }
        }
        else
        {
            emit("id ", id, " not found\n");
        }
    }

    void display()
    {
        auto lock = std::unique_lock<std::mutex>(m_);
        for (auto&& c : v_)
        {
            c.display();
        }
    }

    auto shutdown() -> void
    {
        for (auto&& c : v_)
            c.stop();
    }

private:
    std::mutex m_;
    std::vector < component > v_;
};

int main() {
    int choose;
    int type;
    int id;
    std::string name;
    component_set components;

    do {
        emit("1.ADD A COMPONENT\n"
             "2.DISPLAY A COMPONENT\n"
             "3.START MONITORING\n"
             "4.STOP MONITORING\n"
             "5.QUIT\n");
        std::cin >> choose;
        switch (choose) {
        case 1:
            emit("enter type, id and name:\n");
            std::cin >> type >> id >> name;
            components.add(type, id, name);
            // fall through
        case 2:
            components.display();
            break;

        case 3:
            emit("ID to be monitored\n");
            std::cin >> id;
            components.start(id);
            break;

        case 4:
            emit("ID to be stopped\n");
            std::cin >> id;
            components.stop(id);
            break;
        }
    } while (choose != 5);
}
...