C++ REST SDK中的异步任务库PPLX

简介

C++ REST SDK中提供了PPLX用来支持异步操作,姑且可以认为PPLX是微软PPL-并行模式库/并发运行时任务并行task部分。

C++ REST SDK中,对于task的使用也是推荐开发者查阅并发运行时部分,在任务并行(并发运行时)可以对其进行了解。
Programming with Tasks中描述了C++ REST SDK中对任务编程的基本信息。

目标

在以下内容中,将了解PPL的任务部分,也就是task的使用方法,由此了解异步操作如何实现:

  1. 任务的创建及运行
  2. 任务的合并
  3. 任务的取消
  4. 处理异常
  5. 其它

任务的创建及运行

task构造时,构造参数可以为可调用对象或者task_completion_event,譬如:

//构造函数
auto task = pplx::task<int>([](){
    return 10;
});
 
//lambda
auto task = []()->pplx::task<int>{
    return pplx::task_from_result(10);
};
 
//create_task
auto task = pplx::create_task([](){
    return 10;
});
 
//create_task的另一种方式
pplx::task_completion_event<int> tce;
auto task = pplx::create_task(tce);

添加延续任务使用task.then形成异步工作链:

auto s = std::make_shared<std::string>("Value 1");
 
return pplx::create_task([s]{
    std::cout <<"Current Valus:" << *s << std::endl;
    *s = "Value 2";
    //异步任务1
}).then([s]{
 
    std::cout << "Current Valus:" << *s << std::endl;
    *s = "Value 3";
    return *s;
    //异步任务2
}).then(异步任务3)....

上述示例会依次输出Value 1,Value2,Value3...

使用task.get或者task.wait执行异步任务:

  • get
    阻塞直到任务执行完成,并返回任务结果,当任务取消时,抛出task_canceled异常,发生其它异常也会被抛出;
  • wait
    等待任务到达终止状态,然后返回任务状态:completed、canceled,如果发生异常会被抛出。

任务的合并

when_all 或者 &&

返回合并任务,只有当所有任务都完成时合并任务才会返回成功;如果任何一个任务被取消或者抛出异常,则合并任务会完成并处理取消状态,在合并任务get或者wait时抛出异常,示例如下:

std::array<pplx::task<void>, 3> tasks = {
    pplx::create_task([] { std::cout << "Hello from taskA." << std::endl; }),
    pplx::create_task([] { std::cout << "Hello from taskB." << std::endl; }),
    pplx::create_task([] { std::cout << "Hello from taskC." << std::endl; })
};
 
auto joinTask = pplx::when_all(std::begin(tasks),std::end(tasks));
 
std::cout<<"Hello from the joining thread."<<std::endl;
joinTask.wait();//等待任务完成

如果任务类型为task<T>,则合并任务类型为task<vector<T>>

when_any 或者 ||

返回合并任务,当任何任务完成时合并任务就会返回成功;如果所有任务都被取消或者抛出异常,则合并任务会完成并处理取消状态,并且如果任何任务发生异常,在合并任务get或者wait时抛出异常。

合并任务返回类型为task<size_t>,即返回完成任务的索引。

任务的取消

pplx::cancellation_token_source中包裹了cancellation_token,用来提供取消操作,通过cancellation_token.is_canceled()在执行任务的过程中判断任务是否要被取消:

pplx::cancellation_token_source cts;
std::cout<<"Creating task..."<<std::endl;
 
auto task = pplx::create_task([cts]{
    bool moreToDo = true;
    while (moreToDo)
    {
       if (cts.get_token().is_canceled())//判定是否被取消了
       {
           return;
       }
       else
       {
           moreToDo = []()->bool {
               std::cout << "Performing work..." << std::endl;
               pplx::wait(250);
               return true;
           }();
       }
    }
});
 
 
pplx::wait(1000);
 
std::cout<<"Canceling task..."<<std::endl;
cts.cancel();
std::cout<<"Waiting for task to complete..." <<std::endl;
task.wait();
std::cout<<"Done."<<std::endl;

注意cancellation_token_source要使用传值操作,其类似于智能指针。

当要在异步工作链中支持取消时,需要将cancellation_token作为构造task的参数传递,然后结合task.wait判断是否要取消:

pplx::cancellation_token_source cts;
auto task = pplx::task<void>([cts](){
 
    std::cout<<"Cancel continue_task"<<std::endl;
    cts.cancel();
}).then([](){
    std::cout<<"this will not run"<<std::endl;
},cts.get_token());
 
try
{
    if (task.wait() == pplx::task_status::canceled)
    {
        std::cout<<"taks has been canceled"<<std::endl;
    }
    else
    {
        task.get();
    }
}
catch (const std::exception& e)
{
    std::cout <<"exception: "<<e.what()<<std::endl;
}

处理异常

之前说过如果任务发生异常,会在get或者wait时抛出,但是如果希望在异步任务链中判定之前执行是否发生异常做出操作时,可以采用另外的方式。

当使用task.then时一般是这样写的:

task<T>.then([](T t){
     //处理任务结果t
})

这时候进入then时之前的任务已经执行完成了,task.then有另外一种写法,能够在then时并没有执行任务:

task<T>.then([](task<T> task){
       try 
       {
              task.get(); //使用get或者wait执行任务
       }
       catch(...)
       {
           //处理异常
       }
})

其它

  • task_from_result
    从结果直接构造task,用来不再继续执行,返回task<TResult>结果
  • task_from_execption
    从异常构造task
  • task_options
    task创建选项,用来指定task的调度器、取消标志等内容

总结

pplx为我们提供了基于任务的编程模型,为异步编程提供了相对简单的实现方法,后续在C++ REST SDK使用中可以看到其应用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,294评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,780评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,001评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,593评论 1 289
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,687评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,679评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,667评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,426评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,872评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,180评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,346评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,019评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,658评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,268评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,495评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,275评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,207评论 2 352

推荐阅读更多精彩内容