-1

A comment on my question suggested that "SynchronizationContext" is what determines whether tasks run as separate threads or on one thread, but this was not mentioned in any answers to this question, nor to any detail when tasks will actually run in parallel on separate threads or just run on the same thread but perhaps share work between them when waiting on IO.

In particular, I'm looking for a comparison between Thread objects and Task objects in this context, whether they behave identically or differently.

How "async" and "await" connect (or don't connect) to this would be helpful also.

For an illustrative example, let's say I have two actions:

f: Busy non-IO loop for one second
g: Sleep for one second

And lets assume I have a CPU with a ridiculous amount of cores.

Given the following code, whether h = f, or h = g, it should take close to one second to run yes?

Thread x1 = new Thread(h);
Thread x2 = new Thread(h);
Thread x3 = new Thread(h);
Thread x4 = new Thread(h);
Thread x5 = new Thread(h);
x1.Start();
x2.Start();
x3.Start();
x4.Start();
x5.Start();
x1.Join();
x2.Join();
x3.Join();
x4.Join();
x5.Join();

Lets say I do a similar thing for tasks:

Task x1 = new Task(h);
Task x2 = new Task(h);
Task x3 = new Task(h);
Task x4 = new Task(h);
Task x5 = new Task(h);
x1.Start();
x2.Start();
x3.Start();
x4.Start();
x5.Start();
x1.Wait();
x2.Wait();
x3.Wait();
x4.Wait();
x5.Wait();

For the cases h = f and h = g, how long does this task code take to run, and if it depends, what circumstances make the difference and how do I control them?

Clinton
  • 22,361
  • 15
  • 67
  • 163
  • 1
    Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/194757/discussion-on-question-by-clinton-synchronizationcontext-for-tasks). – Samuel Liew Jun 11 '19 at 12:06

1 Answers1

1

In particular, I'm looking for a comparison between Thread objects and Task objects in this context, whether they behave identically or differently.

They're almost identical with the code you have.

There are two different kinds of Tasks: Delegate Tasks, which run code; and Promise Tasks, which represent a Future.

Tasks that you create using the Task constructor and Start are Delegate Tasks. Tasks created using async and await are Promise Tasks.

Delegate Tasks just represent code to be run. They are not the same as threads, but they do run on threads. With your sample code, Start will start these tasks running on TaskScheduler.Current, which is probably the same as TaskScheduler.Default, which means they would run on the thread pool. Since you assume a ridiculous number of cores, then your Delegate Task code would be essentially the same as the manual Thread code, except they run on thread pool threads instead of your own threads.

On a side note, using the Task constructor and Start is so low-level that it doesn't even have any use cases; you should never use the Task constructor because there is always a better solution, no matter what you're trying to do. Check out the higher-level primitives in the Task Parallel Library documentation. In your case, you can do the same thing with a single line of code:

Parallel.Invoke(h, h, h, h, h);
Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810