zoukankan      html  css  js  c++  java
  • C++异步编程 for VS2011(三)

    任务组:

    在之前我们介绍的异步操作都是基于Task<>的,这个是被封装好的类,可以作为传入,或者传出参数。下面我们要介绍的任务组的概念,他是比Task<>更轻量级的异步调用方式。

    在PPL中Concurrency::task_group和Concurrency::structured_task_group,这两个类都是异步操作的任务组,Concurrency::task_handle类是任务组的基本单位。

    我们先用 Concurrency::structured_task_group举例,我们通过structured_task_group::run 去添加任务,这个任务就是 Concurrency::task_handle,他的构造函数参数可以是函数指针,结构体重载()操作符,或者是lambda表达式。我们通过structured_task_group::wait去执行已经添加的任务,或者通过structured_task_group::run_and_wait去添加并执行所有的任务

    #include "stdafx.h"
    #include <ppl.h>
    #include <iostream>
    #include <functional>
    using namespace Concurrency;
    using namespace std;

    const struct functionstruct{
        void operator ()() const
        {
            cout<<"This is override struct operator "<<endl;
        }
    }myfunction;

    void taskfuncton ()
    {
        cout<<"This is function point"<<endl;
    }
    int _tmain(int argc, _TCHAR* argv[])
    {
        // Function point
        auto task1=make_task(&taskfuncton);
        // Struct with () operator
        auto task2 = make_task(myfunction);
        // Lambda express
        auto task3 = make_task([] { cout<<"This is lambed express"<<endl; });

        // Create a structured task group and run the tasks concurrently.

        structured_task_group tasks;

        tasks.run(task1);
        tasks.run(task2);
        tasks.run_and_wait(task3);
        return 0;

    这里要注意一点的就是,这里的task都必须是没有返回值和传入参数的函数,或者lambda表达式。这就是和基于task<>最大的不同,基于task<>的任务组需要用when_all或者when_any来调度,我们可以获得到task<>的返回值,而structured_task_group不允许函数有传入和传出参数。

    我们也可以创建一个数状的任务组,如下图 

     

    对应的代码是

    // task-tree.cpp
    // compile with: /c /EHsc
    #include <ppl.h>
    #include <sstream>
    #include <iostream>
    #include <sstream>

    using namespace Concurrency;
    using namespace std;

    void create_task_tree()
    {   
       // Create a task group that serves as the root of the tree.
       structured_task_group tg1;

       // Create a task that contains a nested task group.
       auto t1 = make_task([&] {
          structured_task_group tg2;

          // Create a child task.
          auto t4 = make_task([&] {
             // TODO: Perform work here.
          });

          // Create a child task.
          auto t5 = make_task([&] {
             // TODO: Perform work here.
          });

          // Run the child tasks and wait for them to finish.
          tg2.run(t4);
          tg2.run(t5);
          tg2.wait();
       });

       // Create a child task.
       auto t2 = make_task([&] {
          // TODO: Perform work here.
       });

       // Create a child task.
       auto t3 = make_task([&] {
          // TODO: Perform work here.
       });

       // Run the child tasks and wait for them to finish.
       tg1.run(t1);
       tg1.run(t2);
       tg1.run(t3);
       tg1.wait();   

     我们可以通过structured_task_group::cancel 在内部或者外部来取消整个任务组,通过structured_task_group::is_canceling 来得到取消状态。

    对于异常我们要在.wait()方法外面加try_catch

    structured_task_group tg2;

    // Create a child task.      
    auto t4 = make_task([&] {
       // Perform work in a loop.
       for (int i = 0; i < 1000; ++i)
       {
          // Call a function to perform work.
          
    // If the work function fails, throw an exception to 
          
    // cancel the parent task.
          bool succeeded = work(i);
          if (!succeeded)
          {
             throw exception("The task failed");
          }
       }         
    });

    // Create a child task.
    auto t5 = make_task([&] {
       // TODO: Perform work here.
    });

    // Run the child tasks.
    tg2.run(t4);
    tg2.run(t5);

    // Wait for the tasks to finish. The runtime marshals any exception
    // that occurs to the call to wait.
    try
    {
       tg2.wait();
    }
    catch (const exception& e)
    {
       wcout << e.what() << endl;

    }

    上面说完了  Concurrency::structured_task_group,Concurrency::task_group 的使用方法基本上和前者类似。但是后者比前者更灵活,同样消耗的资源也更多。

    下面是他们两个之间不同的地方。 

    1. task_group是线程安全的,可以在别的线程里面通过run添加task, structured_task_group不允许多线程操作,而且所有的操作必须写在一个线程代码块里。

    2.  task_group可以再wait()方法执行之后,再通过run 方法添加task,而structured_task_group是固定的,.wait()后不能再添加。

    3. structured_task_group 建立的任务组树,子节点必须在父节点里面调用wait()的方法,因为structured_task_group只能在一个线程代码块里面执行,所以子节点必须要调用wait(),而task_group不需要。

    4.task_group 添加任务不需要调用make_task()方法, structured_task_group 必须调用。

        task_group tasks;

        tasks.run(&taskfuncton);
        tasks.run(myfunction);

        tasks.run_and_wait([] { cout<<"This is lambed express"<<endl; }); 

    总之, task_group较之structured_task_group又多封装了很多东西,如果没有特殊需要structured_task_group可以写出更高效的代码。

     引用自:

    http://msdn.microsoft.com/en-us/library/windows/apps/dd492427(v=vs.110).aspx 
    http://msdn.microsoft.com/en-us/library/windows/apps/dd984117(v=vs.110).aspx

  • 相关阅读:
    Linux 学习 step by step (1)
    ubuntu server nginx 安装与配置
    ubuntu server samba服务器配置
    iOS app集成支付宝支付流程及后台php订单签名处理
    mac 连接windows 共享内容
    linux 文件查找,which,whereis,locate,find
    ubuntu server vsftpd 虚拟用户及目录
    ubuntu server 安装 mantis bug tracker 中文配置
    ubuntu server vsftpd 匿名用户上传下载及目录设置
    linux 用户管理,用户权限管理,用户组管理
  • 原文地址:https://www.cnblogs.com/zjjcy/p/2432494.html
Copyright © 2011-2022 走看看