PPL task的理解

// testasync.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "ppltasks.h"
#include "iostream"
#include <array>
#include <numeric>
#include <time.h>
#include <sstream>
#include<windows.h> 
using namespace std;
using namespace Concurrency;
int testasync();
void DeleteWithTasksHandleErrors(string  fileName);
int main()
{
	task<int>t([]() {
		return 10;
	});//task<int>定义了一个并行任务并设定返回int型值,t的初始化用到了lambda表达式,其中涉及到了一个异步处理(return 10),wait()会等待异步处理结束,
	//从get()方法能得到异步处理的返回值。这里主要用到了Concurrency::task这个类
	//t.wait();
	auto ta = t.then([](int n) {return n + 10; });
	//这里通过then()方法又加了一个异步处理,第一个return返回的10会作为第二个异步处理Lambda匿名函数的参数,
	//get()方法得到n+10的结果。在这里then方法返回的还是task<int>对象,所以如果后续还要追加其他任务可以
	//t.then([]{}).then([]{}).then([]{}).....
	//这里通过then()方法追加的延长任务(Continuation task)有Value-Based和Task-Based两种
	/******
	VALUE BASED:
	t.then([](int n){});
	TASK-BASED:
	t.then([](task<int>preTask){});
	*/
	//两者的区别是Value-Based类型的延长任务在前序任务被取消或者发生异常时就不会被执行,而task-based类型延长任务仍旧会被执行
	//还有其他的Concurrency::task   Concurrency::when_all   Concurrency::when_any
	wcout << ta.get() << endl;
	char c = getchar();
    return 0;
}
int testasync()
{
	array<task<int>, 3> tasks = {
		task<int>([] { Sleep(3000); cout << "the f1 output\n"; Sleep(10000);  return 100; }),
		task<int>([] { Sleep(1000); cout << "the f2 output\n"; Sleep(10000); return 10; }),
		task<int>([] { Sleep(2000); cout << "the f3 output\n"; Sleep(10000); return 1; })
	};

	//when_all().wait():容器里面所有的task都被执行后,才继续向下执行。  
	//when_any().wait():容器里第一个task完成之后,就继续向下执行。  
	auto TaskList = when_all(tasks.begin(), tasks.end())
		.then([](vector<int> results)
	{
		cout << "The sum is "
			<< accumulate(results.begin(), results.end(), 0)
			<< endl;
	});

	time_t t1 = time(NULL);

	cout << "begin\n";

	TaskList.wait();

	cout << "end\n";

	time_t t2 = time(NULL);

	cout << "the runtime length " << t2 - t1 << "s " << endl;
}
/*
异步编程中,常见的做法时定义一个操作序列,也称作任务链。其中每个延续只有在前一个延续完成后才能执行。
在某些情况下,上一个先行任务会产生一个被延续接受为输入的值。通过使用task:then方法,你可以按照直观且
简单的方式创建任务链。该方法返回一个task<T>,其中T是lambda函数的返回类型。你可以将多个延续组合到一个任务链中
myTask.then(......).then(......).then(......);当延续创建一个新的异步操作时,任务链尤其有用,此类任务成为异步任务。
以下示例介绍具有两个延续的任务链。初始任务获取一个现有文件的句柄,当操作完成后,第一个延续会启动一个新的异步操作
来删除该文件。当该操作完成后,第二个延续将运行,并且输出一条确认消息。

#include <ppltasks.h>
using namespace concurrency;
...
void App::DeleteWithTasks(String^ fileName)
{
using namespace Windows::Storage;
StorageFolder^ localFolder = ApplicationData::Current::LocalFolder;
auto getFileTask = create_task(localFolder->GetFileAsync(fileName));

getFileTask.then([](StorageFile^ storageFileSample) ->IAsyncAction^ {
return storageFileSample->DeleteAsync();
}).then([](void) {
OutputDebugString(L"File deleted.");
});
}
注:
1.第一个延续将IAsyncAction对象转换为task<void>并返回task。
2.第二个延续执行无错误处理,因此接受void而非task<void>作为输入,它时一个基于值的延续。
3.第二个延续直至DeleteAsync操作完成后才执行。
因为第二个延续是基于值的,所以如果通过调用DeleteAsync启动的操作引发异常,则第二个延续根本不会执行。

4.创建任务链只是使用task类组合异步操作的一种方式。还可以通过使用连接和选择运算符&&和||来组合操作。

*/

/*
-----------------通过任务使用异步操作-------------
以下示例说明如何利用返回IAsyncOperation接口且其操作会生成一个值的async方法。基本步骤:

1.调用create_task方法将其传递到IAsyncOperation对象
2.调用任务上的成员函数task::then并且提供一个将在异步操作完成时调用的lambda

#include <ppltasks.h>
using namespace concurrency;
using namespace Windows::Devices::Enumeration;
...
void App::TestAsync()
{
//Call the *Async method that starts the operation.
IAsyncOperation<DeviceInformationCollection^>^ deviceOp =
DeviceInformation::FindAllAsync();

// Explicit construction. (Not recommended)
// Pass the IAsyncOperation to a task constructor.
// task<DeviceInformationCollection^> deviceEnumTask(deviceOp);

// Recommended:
auto deviceEnumTask = create_task(deviceOp);

// Call the task’s .then member function, and provide
// the lambda to be invoked when the async operation completes.
deviceEnumTask.then( [this] (DeviceInformationCollection^ devices )
{
for(int i = 0; i < devices->Size; i++)
{
DeviceInformation^ di = devices->GetAt(i);
// Do something with di...
}
}); // end lambda
// Continue doing work or return...
}
*/

/*
-----------------------------------------------------------------
*****************************Lambda函数返回类型和任务返回类型*************
在任务延续中,lambda函数的返回类型包含在task对象中。如果该lambda返回double,则延续任务的类型为task<double>
但是任务对象的设计目的是为了不生成无需嵌套的返回类型,如果lambda返回IAsyncOperation<SyndicationFeed>^,则延续
返回task<SyndicationFeed^>,而不是task<<SyndicationFeed^>>或者task<IAsyncOperation<SyndicationFeed^>>
此过程成为异步解包,并且它还确保延续内部的异步操作在调用下一个延续之前完成。
-----------------------------------------------------------------
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值