Paul Selles

Computers and cats

Task Parallelism: Passing Values into a Tasks

One road block that I stubble upon when starting to work with Task Parallelism is passing values into my Tasks. Here is a quick guide to help get you head around this issue.

 

We can easily create a single task that takes in non-changing values within a function and run it getting expected results:

int i = 0;
int j = 1;
int k = 2;

Task task = Task.Factory.StartNew(() =>
    {
        Console.WriteLine(string.Format("i='{1}'{0}j='{2}'{0}k='{3}'{0}{0}", Environment.NewLine, i, j, k));
    });

task.Wait();
Console.ReadLine();

Results:

i=’0′
j=’1′
k=’2′

 

Once the the values start changing then the Tasks will run against the latest values rather than the original value when the Task was created. The values are not fixed within the scope of the Task itself but rather in the scope of the parent function, so the variables do not preserve the value from when the Task was created:

int i = 0;
int j = 1;
int k = 2;

Task task = Task.Factory.StartNew(() =>
    {
        Console.WriteLine(string.Format("i='{1}'{0}j='{2}'{0}k='{3}'{0}{0}", Environment.NewLine, i, j, k));
    });

i = -1;
j = -1;
k = -1;

task.Wait();
Console.ReadLine();

Results:

i=’2′
j=’2′
k=’2′

i=’2′
j=’2′
k=’2′

i=’2′
j=’2′
k=’2′

i=’2′
j=’2′
k=’2′

i=’2′
j=’2′
k=’2′

i=’2′
j=’2′
k=’2′

i=’2′
j=’2′
k=’2′

i=’2′
j=’2′
k=’2′

What happened here is that all the loops completed before any of the tasks had a chance to run (all the loops incrementing incremented to 2 before failing the for condition).

 

We can get around the problem a couple of ways, first we can reassign the values to an unchanging variable that shares the same scope as our Task. This will ensure that when ours Tasks are created the values that they use will be assigned uniquely for that instance. If we choose this route then our code will look like this:

List<Task> tasks = new List<Task>();

for (int i = 0; i < 2; i++)
{
	for (int j = 0; j < 2; j++)
	{
		for (int k = 0; k < 2; k++)
		{
			int I = i;
			int J = j;
			int K = k;

			tasks.Add(Task.Factory.StartNew(() =>
			{
				Console.WriteLine(string.Format("i='{1}'{0}j='{2}'{0}k='{3}'{0}{0}", Environment.NewLine, I, K, J));
			}));
		}
	}
}

Results:

i=’0′
j=’0′
k=’0′

i=’0′
j=’1′
k=’0′

i=’0′
j=’1′
k=’1′

i=’1′
j=’0′
k=’0′

i=’1′
j=’1′
k=’0′

i=’1′
j=’0′
k=’1′

i=’0′
j=’0′
k=’1′

i=’1′
j=’1′
k=’1′

Though the Tasks may not have completed in order, all the tasks are present and all the values have been accounted for.

 

Finally, my favourite solution, passing all the variables as an Anonymous Type to the Task [1]. Within the Task the object will have to be casted to a dynamic type to access all the Anonymous Type’s members [2]. The reason why I like this solution is that it lends itself well to working with more complicated data types without having to reassign a large number of variables locally. For our above example our solution will look like this:

List<Task> tasks = new List<Task>();

for (int i = 0; i < 2; i++)
{
    for (int j = 0; j < 2; j++)
    {
        for (int k = 0; k < 2; k++)
        {
            tasks.Add(Task.Factory.StartNew((Object obj) =>
            {
                var data = (dynamic)obj;
                Console.WriteLine(string.Format("i='{1}'{0}j='{2}'{0}k='{3}'{0}{0}", Environment.NewLine, data.i, data.k, data.j));
            }, new { i = i, j = j, k = k }));
        }
    }
}

Task.WaitAll(tasks.ToArray());
Console.ReadLine();

And the results will be similar to those above.

 

Paul

 

References

 

[1] Anonymous Types (C# Programming Guide). MSDN Library.

[2] Using Type dynamic (C# Programming Guide). MSDN Library.

Advertisements

One response to “Task Parallelism: Passing Values into a Tasks

  1. Rio July 10, 2015 at 2:58 pm

    Thanks! This helped me a lot. For the life of me I could not figure out what was going on with my tasks lol.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: