STL任务库简介

来源:互联网 发布:c语言奇数阶幻方 编辑:程序博客网 时间:2024/05/19 09:11

管理任务

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

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

    int main()
    {
        printf_thread_id("Main Thread");
        std::future<constchar*> 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(constchar*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函数是捕获不到异常的。 

0 0
原创粉丝点击