C++異步編程 for VS2011(一)


微軟已經在VS10中加入了Concurrency Runtime namespace來支持C++的異步編程,筆者認為異步編程在是現代編程語言的一個發展方向。在此總結一些異步編程的基本概念和語法,希望能給大家理解異步編程帶來一些方便。

 

 首先,異步編程的基本單位是task class。我們把想要執行異步操作的函數放入task 里面,通過協調這些task的關系,來實現基於函數的異步操作。這種方式相對於傳統的基於線程池的異步調用,開發者不需要關心底層的線程如何分配,資源如何同步,是否有死鎖的存在。這樣,開發者會更專注於代碼的邏輯,進而提高編程的效率。

 

 task<T> 是一個模板類,T是函數返回值的類型,比如task<int> t([](){return 1;}),或者函數返回值為空task<void> t([](){return;})。task的構造函數傳入參數可以是lambda表達式。我們聲明了一個task之后,通過調用wait()方法去執行他,對於有返回值的task,我們調用.get()方法去取得他的返回值。下面是一個簡單的例子

#include <ppltasks.h>
#include <iostream>

using  namespace Concurrency;
using  namespace std;

int wmain()
{
    task< int> t([]() {
         return  42;
    });

    t.wait();
    wcout << t. get() << endl;
}

 

我們可以用.then()的方法去指定一個連續的任務,就是在前一個task完成之后立刻執行.then()里面的函數。這個函數要求接受前一個任務返回的結果。比如前一個任務中函數返回的是int 那么在.then()的函數里面就要指定傳入參數為int的lambda表達式()[int res]{ res++;}。.then()方法只要求傳入參數和上一個任務相同,而返回值可以不同。比如下面的代碼,第一個task返回int,在第一個then中返回void,然后返回int,最后返回void。這里要注意的是,在最后一個then()中調用wait,而不是t.wait(),否則第一個.then 不會執行。

    task< int> t([]() {
         return  42;
    });

    t.then([]( int res){wcout<< " Hello ";}).then([](){ return  1;}).then([]( int res){wcout<<res<<endl;}).wait();
    wcout << t. get() << endl;

 

這段代碼展示的是如何嵌套task,注意這里的返回值雖然是task<int>,但是外面的task的參數依然是int,這兩個參數要保持一致。

    task< int> t([]() { 
        wcout << L " Task A " << endl;

         //  Create an inner task that runs before any continuation
        
//  of the outer task.
         return task< int>([]() {
            wcout << L " Task B " << endl;
             return  1;
        });
    });

 

 一組task的執行,我們可以把一組task放入到容器里,然后通過when_all(),這個函數去執行他們,when_all傳入參數是容器迭代器的開始和結束。這里要求容器里面的task的返回值必須相同。這是沒有返回值的例子

     // Start multiple tasks.

    array<task< void>,  3> tasks = {
        task< void>([] { wcout <<  " Hello from taskA. " << endl; }),
        task< void>([] { wcout <<  " Hello from taskB. " << endl; }),
        task< void>([] { wcout <<  " Hello from taskC. " << endl; })
    };

    auto joinTask = when_all(tasks.begin(), tasks.end());

     //  Print a message from the joining thread.
    wcout <<  " Hello from the joining thread. " << endl;

     //  Wait for the tasks to finish.
    joinTask.wait();

 

這是有返回值的例子,注意when_all().then 的傳入參數是vector<T> 

//  Start multiple tasks.
array<task< int>,  3> tasks = {
    task< int>([] {  return  88; }),
    task< int>([] {  return  42; }),
    task< int>([] {  return  99; })
};

auto joinTask = when_all(tasks.begin(), tasks.end())
                .then([](vector< int> results)
    {
        wcout <<  " The sum is  " 
              << accumulate(results.begin(), results.end(),  0)
              << L ' . ' << endl;
    });

//  Print a message from the joining thread.
wcout <<  " Hello from the joining thread. " << endl;

//  Wait for the tasks to finish.
joinTask.wait();

 

when_all().wait()是當容器里面所有的task都被執行后,才繼續向下執行。而when_any().wait()就是當容器里第一個task完成之后,就繼續向下執行。和when_all 一樣,when_any 要求task的返回值相同 。但是,when_any().then()的傳入參數是pair<T, size_t> pair.first 是task的返回值,pair.second是已經完成的task的序號。

     //  Start multiple tasks.
    array<task< int>,  3> tasks = {
        task< int>([] {  return  88; }),
        task< int>([] {  return  42; }),
        task< int>([] {  return  99; })
    };

     //  Select the first to finish.
    when_any(tasks.begin(), tasks.end())
        .then([](pair< int, size_t> result)
        {
            wcout <<  " First task to finish returns  "
                  << result.first
                  << L "  and has index  "
                  << result.second
                  << L ' . ' << endl;
        }).wait();   

 

這篇文章是這個系列的第一篇,旨在向大家介紹一些基本的概念和用法。我會在接下來的系列中,給大家展示一些更深層次的東西。 

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM