Quantcast
Channel: WE MOVED to github.com/microsoft/cpprestsdk. This site is not monitored!
Viewing all articles
Browse latest Browse all 4845

New Post: help with task cancellation

$
0
0
Here is a condensation of what I'm doing.

observe_all_exceptions() is lifted directly from here. get_vector_of_tasks() is a stand-in for the actual much-more-complex source of the vector<tasks_t> so don't take it too seriously. The code following it, though, is pretty much verbatim from the application, minus extraneous stuff that doesn't pertain to the use of observe_all_exceptions(). Both that code and the real get_vector_of_tasks() are class member functions in the actual code.

The key requirement is that all tasks returned by get_vector_of_tasks() be created with cancel_token, and that they check and respond to it reasonably quickly during operation. Otherwise, observe_all_exceptions() can take a while.
typedef std::vector<pplx::task<web::json::value>> tasks_t;
//...
template<class T, class InIt>
void observe_all_exceptions(InIt first, InIt last)
{
    std::for_each(first, last, [](pplx::task<T> t)
    {
        t.then([](pplx::task<T> previousTask)
        {
            try { previousTask.get(); }
            catch (std::exception const &x) {
                log_debug("observe_all_exceptions: task ends with exception [%s]", x.what());
            }
            catch (...) {
                log_debug("observe_all_exceptions: task ends with exception [catchall exception]");
            }
        });
    });
}

tasks_t get_vector_of_tasks(concurrency::cancellation_token cancel_token)
{
    using namespace web::http;
    
    client::http_client client(U("http://some.web.site"));
    tasks_t rtn;
    for (int i = 0; i < 10; ++i)
    {
        http_request request(methods::GET);
        http_headers &headers = request.headers();
        headers.add(header_names::accept, U("application/json"));

        web::uri uri;
        //... make uri unique
        
        auto task = client.request(request, cancel_token).then(
        [uri](http_response response) -> pplx::task<web::json::value>
        {
            status_code status = response.status_code();
            if (response.status_code() >= 400)  //one possible source of exceptions
            {
                utility::ostringstream_t msg;
                msg << U("URI: [") << uri.to_string() << U("] ")
                    << U("response: [") << response.status_code()
                    << U(' ') << response.reason_phrase()
                    << U(' ') << response.extract_string().get().substr(0, 128) << U(']');
                throw http_exception(msg.str());
            }   //if
            return response.extract_json();
        });
        rtn.push_back(task);
    }   //for
    return rtn;
}

concurrency::cancellation_token_source cts;
tasks_t tasks;
try {

tasks = get_vector_of_tasks(cts.get_token()).get();

while (!tasks.empty())
{
    auto sep = std::partition(std::begin(tasks), std::end(tasks),
        [](pplx::task<web::json::value> task){ return !task.is_done(); });
    if (0 == std::distance(sep, std::end(tasks)))
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        continue;
    }   //if
    for (auto task_it = sep; task_it != std::end(tasks); ++task_it)
    {
        auto const &task = *task_it;
        auto json = task.get();
        auto result_json = json[U("result")].as_array();
        for (auto result : result_json)
        {
            //... non-thread-safe consumer of result is called here
        }   //for
    }   //for
    tasks.erase(sep, tasks.end());
}   //while

}
catch (...)
{
    cts.cancel();   //tasks must timely pay attention to this
    observe_all_exceptions<web::json::value>(std::begin(tasks), std::end(tasks));
    throw;
}
-evan

Viewing all articles
Browse latest Browse all 4845

Latest Images

Trending Articles



Latest Images

<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>