4

I used the visual c++ concurrency runtime to create a task and then scheduled four continuations on it

#include <iostream>
#include <thread>
#include <ppltasks.h>

int main()
{
    concurrency::create_task([]
    {
        std::cout << std::this_thread::get_id() << std::endl;
    })
    .then([]
    {
        std::cout << std::this_thread::get_id() << std::endl;
    })
    .then([]
    {
        std::cout << std::this_thread::get_id() << std::endl;
    })
    .then([]
    {
        std::cout << std::this_thread::get_id() << std::endl;
    })
    .then([]
    {
        std::cout << std::this_thread::get_id() << std::endl;
    });

    std::cin.get();
}

This prints the following output

29432
29432
25096
25668
42488

Notice the 4 continuations are not scheduled on the same thread as the initial task. Is there a way to schedule the continuations on the same thread as the initial task? I believe this is possible in c# by using TaskContinuationOptions.ExecuteSynchronously option.

tcb
  • 4,408
  • 5
  • 34
  • 51
  • 1
    Much of the point of things like the concurrency runtime is to *avoid* dealing with details like explicitly deciding which tasks run on which threads. You should be specifying result-oriented constraints (like requirements on ordering) and let the runtime deal with the details. – Jerry Coffin May 21 '15 at 16:12
  • 1
    @JerryCoffin While I generally agree with your point, I can see reasons that one would want that; thread creation may have arbitrary overhead depending on platform. Not being able to force the runtime to schedule subsequent tasks to the same thread makes it unusable for certain use cases. – Jonas Schäfer May 21 '15 at 17:44
  • @JonasWielicki: Have you considered using a dummy variable between the tasks? That might cause the runtime to use a single thread to avoid passing the object between threads. – Guvante May 21 '15 at 17:57

1 Answers1

0

Ordinarily, you can control the context in which continuations execute using task_continuation_context, as the MSDN documentation describes. However, the same documentation also mentions that:

It is only useful to use this class from a Windows Store app. For non-Windows Store apps, the task continuation's execution context is determined by the runtime, and not configurable.

It seems from your code snippet that while you are using the Concurrency runtime you are not using it from a Windows Store app. Therefore, the context will effectively always be arbitrary.

There's also the question of why you would want to explicitly run subsequent tasks on the same thread as the first task: why not just put those tasks' code inside the first task, then? The point of continuations is to come back to a particular thread in order to continue work that completed in a background task - meaning, the first task will necessarily be the background work you wish to do, and the continuations are reacting to that work from the main, initiating thread. If you wish to stay on the background thread, then stay there and don't bother putting that work in a continuation. (However, as mentioned above, since this isn't a Windows Store app, all of these continuations and tasks run in an arbitrary context; the runtime will just choose an available thread that's convenient.)