开发 Windows 8 Bing地图应用(5)

TripOptimizerImpl::OptimizeTripAsync方法调用TripOptimizer::OptimizeTrip方法作为异步操作的一部分,TripOptimizer::OptimizeTrip方法调用TripOptimizer::CreateGraph创建出行路线的图像,每个位置由一个节点表示,并且每个节点对由棱边相连,一个节点包含了一个位置的名称,经纬度等信息,而棱边包含两点间的距离,相关代码如下。

//创建表示出游地形的图像

void TripOptimizerImpl::CreateGraph(

const vector<wstring>& waypoints,

vector<shared_ptr<Node>>& nodes,

vector<shared_ptr<Edge>>& edges)

{

// 创建一个节点对象,每个对象包含的字符串代表一个位置

for_each(begin(waypoints), end(waypoints), [&nodes](const wstring& waypoint) {

// 对集合添加节点对象

nodes.push_back(make_shared<Node>(waypoint));

});

//

// 创建棱边,形成节点全连接的图像

//

for (auto iter = begin(nodes); iter != end(nodes); ++iter) {

auto node1 = *iter;

for_each(iter + 1, end(nodes), [this, &node1, &edges](shared_ptr<Node> node2) {

//创建棱边对

edges.push_back(make_shared<Edge>(node1, node2));

});

}

}

TripOptimizerImpl::OptimizeTrip方法在3个阶段执行线路优化操作。第一个阶段中,这个方法获取Bing Maps传来的位置信息数据;第二个阶段中,这个方法获取路线中每两点间,可能的路由信息;第三阶段中,这个方法执行线路优化算法。任务的Continuation(Continuation意为在每件事完成之后还要做的事)使得任务完成后可接着运行一个或多个任务。但注意,由于Continuation在后台的运行,需要存储在这些任务中共享的变量,从而使任务可以稍后就能访问它们。TripOptimizerImpl类定义了OptimizeTripParams结构体,这个结构体保留着对TripOptimizer::OptimizeTripAsync方法,和任务间共享变量的输入,有关代码如下。

// 包含出行优化整个过程中,所使用的变量

// 创建这个结构体为的是,使通用参数轻松在连续的任务间传递。

struct OptimizeTripParams

{

//

// 对OptimizeTripAsync的输入

std::vector<std::wstring> Waypoints;

std::wstring TravelMode;

std::wstring Optimize;

std::wstring BingMapsKey;

double Alpha;

double Beta;

double Rho;

unsigned long Iterations;

bool Parallel;

//

// 定时器变量

// 以下时间作为进度信息发送出去

// 总体时间

ULONGLONG TotalTime;

// 总体时间和所花费的HTTP请求时间

ULONGLONG HttpTime;

// 执行优化算法花费的时间

ULONGLONG SimulationTime;

// 位置图像

// 节点对象的集合,每个位置一个节点

std::vector<std::shared_ptr<AntSystem::Node>> Nodes;

// 棱边对象的集合,有(n * (n - 1) / 2)个棱边,其中n代表节点个数

std::vector<std::shared_ptr<AntSystem::Edge>> Edges;

// 对目前批处理挂起的HTTP请求数量

long RequestsPending;

// 保留在线路优化过程的第一阶段未解决的位置

Concurrency::concurrent_vector<std::shared_ptr<AntSystem::Node>> UnresolvedLocations;

};

通过使用一个std::shared_ptr对象,TripOptimizer::OptimizeTripAsync方法创建一个OptimizeTripParams结构体,并将其传递任务链中的每个Continuation,代码如下。

auto params = make_shared<OptimizeTripParams>();

for_each(begin(waypoints), end(waypoints), [params](String^ waypoint) {

params->Waypoints.push_back(waypoint->Data());

});

params->TravelMode = wstring(travelMode->Data());

params->Optimize = wstring(optimize->Data());

params->BingMapsKey = UriEncode(bingMapsKey->Data());

params->Alpha = alpha;

params->Beta = beta;

params->Rho = rho;

params->Iterations = iterations;

params->Parallel = parallel;

5)HTTP相关处理。C++组件定义了HttpRequest类处理HTTP请求,本类使用IXMLHTTPRequest2接口处理HTTP请求。IXMLHTTPRequest2接口只支持异步操作,为使调用函数更容易使用这些异步的操作,HttpRequest::StartDownload方法返回一个Concurrency::task<std::tuple<HRESULT, std::wstring>>对象,这个对象将状态码和HTTP响应作为一个字符串包含其中。

由于IXMLHTTPRequest2只支持异步操作,所以从HTTP服务器请求数据时,必须提供一个IXMLHTTPRequest2Callback对象。HttpRequest.cpp文件定义了HttpRequestCallback类,此类是从IXMLHTTPRequest2Callback继承来的,并实现其方法。

Concurrency::task_completion_event类是很重要的一部分,在其他异步任务完成时,它使得HttpReader类创建一个任务,这个类在将任务对象,还有通过回调函数完成的异步操作,组合在一起的时候很有用。当下载操作完成时,HttpRequestCallback::OnResponseReceived方法设置结束事件,代码如下。

m_completionEvent.set(make_tuple<HRESULT, wstring>(S_OK, ss.str()));

相应地,HttpRequestCallback::OnError方法在错误发生时设置结束事件,这种情况下,任务的输出结果会是错误代码和空字符串,代码如下。

m_completionEvent.set(make_tuple<HRESULT, wstring>(hrError, wstring()));

HttpRequestCallback类同样在下载任务取消时,设置结束事件,这种情况下,任务的输出结果会是S_OK和空字符串,代码如下。

m_completionEvent.set(make_tuple<HRESULT, wstring>(S_OK, wstring()));

HttpRequest::StartDownload函数打开异步请求,创建一个HttpRequestCallback对象,之后其创建一个task对象,在HttpRequestCallback对象的任务结束事件完成时就结束,代码如下。

// 开始指定URI的下载

task<tuple<HRESULT, wstring>> HttpRequest::StartDownload(

const wstring& method,

const wstring& uri,

cancellation_token cancellationToken)

{

// 创建一个IXMLHTTPRequest2对象

IXMLHTTPRequest2* xhr;

HRESULT hr = CoCreateInstance(

__uuidof(FreeThreadedXMLHTTP60),

nullptr,

CLSCTX_INPROC,

__uuidof(IXMLHTTPRequest2),

reinterpret_cast<void**>(&xhr));

SUCCEEDED(hr) ? 0 : throw hr;

// 创建回调函数

auto callback = new HttpRequestCallback(xhr, cancellationToken);

callback->AddRef();

// 打开并发送请求

hr = xhr->Open(method.c_str(), uri.c_str(), callback, nullptr, nullptr, nullptr, nullptr);

SUCCEEDED(hr) ? 0 : throw hr;

hr = xhr->Send(nullptr, 0);

SUCCEEDED(hr) ? 0 : throw hr;

// 操作结束时返回一个完成的任务

task<tuple<HRESULT, wstring>> result(callback->m_completionEvent);

return result.then([callback](task<tuple<HRESULT, wstring>> previousTask) {

callback->Release();

return previousTask;

});

}

原文地址:https://www.cnblogs.com/finehappy/p/2858185.html