基于任务编程
在卡萨布兰卡中,所有长时间运行或有可能阻塞的API都是异步的,例如:任何网络请求的API。PPL任务用于表示一些异步任务的完成。为了让卡萨布兰卡在VS2010和其他非windows平台也能使用,我们创建了一个特别版本的PPL任务并把它包含在卡萨布兰卡中。为了让它和PPL和平共处,我们把该版本命名为pplx
。
一个基于任务的操作可能会也可能不会立即结束。例如:当发送一个HTTP消息是,我们最后将得到一个消息响应。任务最后可得到这样的响应:
web::http::client::http_client client(U("http://localhost:80"));
pplx::task<web::http::http_response> resp = client.request(web::http::methods::GET, U("/foo.html"));
在这儿,任务resp为我们提供了一个将来会用到的值的占位符。只要你有一个任务,实际上,你就需要从这个任务中得到这个值。因为有可能操作完成的很快,任务所绑定的值很快就变得有效,所以有时候我们会去询问任务是否已经完成:
bool done = resp.is_done();
当is_dong()
返回true的时候,我们再用get()
方法去取值,可以确保操作不会block(阻塞):
web::http::http_response response = resp.get();
如果is_done()
返回false,调用'get()'将会导致阻塞线程,这样也就违背了在开始的位置使用异步API目的(保持GUI刷新和服务扩展)。对于这种情况,我们需要采取另外的途径:为任务绑定一个处理器函数,该函数在任务一结束时,就会被调用。我们使用then()
函数:
resp.then([=] (web::http::http_response response)
{
...
});
传递给一个任务的then()
函数对象应该传入一个T或任务的参数:
resp.then([=](pplx::task<web::http::http_response> task)
{
web::http::http_response response = task.get();
...
});
因为我们知道任务已经完成,在回调函数里里调用get()
绝对不会导致阻塞。
网友评论