【问题标题】:I need the thread function to print the random number for every 2 seconds without stopping the actual program我需要线程函数在不停止实际程序的情况下每 2 秒打印一次随机数
【发布时间】:2020-02-25 18:30:42
【问题描述】:
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 秒打印一次。例如:选择“监视”选项时,必须打印值直到按下停止监控。 同时我需要添加组件或在打印时显示它。

【问题讨论】:

  • the1.join(); 放在case 4: 下(可能会检查可连接性)。无论如何,请注意 std::vector 不是线程安全的
  • 另外,thred1() 中的代码应该在循环中 (while (true) { })。你需要一些方法来告诉它结束循环。
  • 那么它将“不在范围内”@DanielLangr
  • @inihsrah 当然,你需要在case 3:之外声明它。
  • 旁注:case 块中不需要括号 { }(除非您声明了局部变量)。

标签: c++ multithreading while-loop do-while


【解决方案1】:

好的,您的代码并不完全有意义,但是当您刚开始使用多线程时可能会感到困惑。

你这样做:

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

此代码的作用是收集您的 ID,创建线程,然后等待线程完成。也许这就是你想要的,但我不明白你为什么要创建一个线程然后立即让主线程阻塞,直到第一个线程完成。

但这就是 the1.join() 所做的——它阻塞主执行线程,直到工作线程完成。这是你想要的吗?

接下来,您的工作线程非常简单。它搜索您的向量,每个循环暂停 1 秒。它不会做任何形式的永远运行。它只是遍历你的向量,搜索你传递给它的值。这就是你想要的吗?

如果不涉及互斥锁和条件变量(如果您要编写多线程编程,您将需要学习这些),我会稍微改变一下。

保持您的代码基本完整...

在主线程中,我会声明一个变量。

thread * myThread = nullptr;

我还要声明一个名为“stopThread”的全局变量:

bool stopThread = false;

对于案例 3,我将其重写为:

案例 3: { 内部标识; cout > id; // 这会杀死旧线程,以防他们执行选项 3 两次。 如果(我的线程!= nullptr){ 停止线程 = 真; 我的线程->加入(); 删除我的线程; } 停止线程 = 假; 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 变量)。你的线程现在循环,直到你告诉它退出。

完全不是我写它的方式,但它与我在对您的代码进行最小更改时所做的很接近。

【讨论】:

  • 我已经解决了之前的问题..现在我必须实现线程的同时运行。当我开始监控一个 ID 并同时再次按下启动监控选项时,我应该能够同时监控两者。
  • ``int id; cout > id; if (myThread!=0) { stopThread = true;我的线程->加入();删除我的线程; } 停止线程 = 假; vec.push_back(thread(thred1,id));我的线程!= 0; break;```它有效,但我无法阻止它。
【解决方案2】:

这不是一个答案,但我发布这个是因为正确的多线程编码并非易事,我想强调一些您可能需要考虑的事情。

这是我对您的问题的解决方案。

有几点(我希望)感兴趣:

  1. 线程被封装在组件中
  2. 组件实现、生命周期和句柄对象按照 1-class-1-job 的原则进行分解
  3. 在控制组件活动时会考虑线程间排序
  4. 通过emit()函数模板控制std::cout的使用互斥。
  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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-03
    • 1970-01-01
    • 1970-01-01
    • 2017-08-18
    • 1970-01-01
    • 2016-09-02
    相关资源
    最近更新 更多