Dot Net For All

Correct way to provide parameter to C# Task

In this article I will discuss the correct way to provide input parameter to the task and not to use the shared variable for the tasks. Before reading further you may want to read my previous articles about tasks.

Using a global variable for Task in C#

Please check the code below in which I am creating ten tasks and using the global variable i to achieve some operation.

        public static void MyMethod()
        {
            for (int i = 0; i < 10; i++)
            {               
                var task = new TaskFactory().StartNew(() =>
                {
                    Console.WriteLine(i);
                });
            }
        }

Let’s run the above code and see the output in below figure.

Task Parameter with output

Whoa, isn’t the output bit weird. Please note that when you execute the code you may get some other output. Our variable is assigned the values from 0 to 9 and the best part is we are not even entering the loop for i = 10. Then what is the reason for such an output.

Lets see the reason. When tasks are started, it is not at all necessary that the task will be started as soon as it is created. And the order of execution is also not confirmed. Means that it is not at all guaranteed that tasks are executed in the order in which they are created.

I hope you get the reason by now. Lets analyse our case. We are starting creating ten tasks. And Since there is always a time gap between the creation and initialization of task. By the time our task is started, there are chances that the loop has reached at the last number i.e 10. It means i is set to 10. And after it is set to 10, rest of the tasks start. And the result is quite not as per our expectations.

This all happened due to the thread synchronization and using a global variable.

Passing a parameter to the Task in C#

We can surely overcome this shortcoming by passing a parameter to the task as shown in below C# code.

        public static void MyTask()
        {
            for (int i = 0; i < 10; i++)
            {
                object arg = i;
                var task = new TaskFactory().StartNew(new Action<object>((test) =>
                {
                    Console.WriteLine(test);
                }), arg);
            }
        }

And we will get the output as shown in the below figure.

Task output with correct parameter

In the above figure we can see the output is as expected. Though it is not in the order in which we executed due to non deterministic behavior to task execution.

In the code we assigned the loop variable to the newly created variable named arg. And the same local variable I am passing as parameter to the task. Hence preventing my tasks to share states.

Conclusion:

In this article we have seen how it can be sometime quite erroneous to pass or use the variable which share states. And how we can save ourselves from this behavior by passing the parameter to the task in C#.

References:

Introduction To Async And Parallel Programming in .NET

TPL Async

Top career enhancing courses you can't miss

My Learning Resource

Excel your system design interview