zoukankan      html  css  js  c++  java
  • STL任务库简介

    管理任务

    在C++ 11的thread库引入了std::async函数,通过它可以非常容易的实现类似于.net中的Task方式的并发。

        void printf_thread_id(const char* name)
        {
            cout << name << " Thread id: " << this_thread::get_id() << endl;
        }

        int main()
        {
            printf_thread_id("Main Thread");
            std::future<const char*> task1 = std::async(std::launch::async, []()
            {
                printf_thread_id("task 1");
                return "hello world";
            });
        
            task1.wait();
            cout << task1.get() << endl;
        }

    可以看到:可以通过std::async函数创建并执行一个任务,返回值为一个future对象,它提供了wait函数等待任务的执行,get函数获取任务的返回值(这个函数内部会调用wait,任务未执行完成的时候会等待),和.Net中的Task非常类似。

    下面是个稍微复杂点的例子:

        #include <iostream>
        #include <future>
        #include <thread>
        using namespace std;

        void printf_thread_id(const char* name)
        {
            cout << name << " Thread id: " << this_thread::get_id() << endl;
        }

        int main()
        {
            printf_thread_id("Main Thread");
            auto begin = chrono::system_clock::now();

            auto task1 = std::async([]()
            {
                printf_thread_id("task 1");
                this_thread::sleep_for(chrono::seconds(1));
                return 3;
            });
        
            auto task2 = std::async([]()
            {
                printf_thread_id("task 2");
                this_thread::sleep_for(chrono::seconds(1));
                return 5;
            });

            task1.wait();
            task2.wait();

            auto end = chrono::system_clock::now();
            cout << "total value " << task1.get() + task2.get() << endl;
            cout << "spent time " << chrono::duration_cast<chrono::milliseconds>(end - begin).count() << endl;
        }

    设置任务的并行方式

    可以通过stl::async函数的第一个参数控制任务的并行方式,它有如下三个取值:

    • launch::async    异步方式。这个方式下,所有任务都会新启动一个线程执行
    • launch::deferred    同步方式。 这个方式下,任务不会新启动线程,串行在创建任务的线程中执行。
    • launch::any    综合方式。 这个方式下,会复用创建任务的线程。

    这个参数也可以不带(我例2中的方式就没有带),默认情况下是launch::any。

    手动控制并发

    前面介绍过可以通过在async函数中通过参数设置并发方式,不过这些基本上都是些自动化的手段,有的时候粗了点,需要我们手动控制。例如:100个任务,但同时最大执行5个并发。

    要手动控制任务,就不能通过async函数启动任务了,必须我们自己手动创建对象,并将其放入线程中执行。示例代码如下:

        #include <iostream>
        #include <future>
        #include <thread>

        int main()
        {
            std::packaged_task<int()> task([](){return 7;}); // wrap the function
            std::future<int> result = task.get_future(); // get a future
            std::thread(std::move(task)).detach(); // launch on a thread
            std::cout << "Waiting...";
            result.wait();
            std::cout << "Done!\nResult is " << result.get() << '\n';
        }

    捕获异常

    和.net中的处理方式一样,任务处理过程中产生的异常可以在任务外通过get函数捕捉,非常方便。

        int main()
        {
            auto ftr = std::async([]()
            {
                throw std::exception("Error occurs !");
            });
        
            try
            {
                ftr.get();
            }
            catch(std::exception & e)
            {
                std::cout << e.what() << std::endl;
            }
        }

    需要注意的是,wait函数并不像.net中的那样会抛异常,通过wait函数是捕获不到异常的。

  • 相关阅读:
    MSI文件的制作
    QPushButton 响应回车 设置默认按钮
    ubuntu 使用apt-fast 安装软件包
    apt命令集使用教程
    如何在windows下使用git及github仓库管理项目
    如何在windows下使用git及github仓库管理项目
    01. struts2介绍
    人生能跨越多少个年代
    联调踩的坑:空和空字符串引发的巨大差异
    我的亲历:一行代码,百万人民币打水漂
  • 原文地址:https://www.cnblogs.com/TianFang/p/2878837.html
Copyright © 2011-2022 走看看