Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing arguments with changing values to Task -- Behaviour?

Tags:

Scenario: An asynchronous task in a loop executes a method containing arguments that change as the program continues:

while(this._variable < 100)
{
    this._variable++; 
    var aTask = Task.Factory.StartNew(() =>
    {
        aList.add(this._variable);
        update(this._savePoint);
    });
}

If the loop runs faster than the tasks complete, will the list add the current value of the variable or is the variable saved locally and the original value added?

like image 213
asunrey Avatar asked Apr 16 '12 18:04

asunrey


People also ask

How does argument pass-by-value work?

In argument pass by value, the argument passing mechanism works by copying each argument into the subroutine area. if any changes to arguments within the subroutine, those changes will not be visible outside the subroutine.

What is argument pass by value in SystemVerilog?

SystemVerilog provides below means for passing arguments to functions and tasks, also, functions and tasks can have default argument values. In argument pass by value, the argument passing mechanism works by copying each argument into the subroutine area.

How to avoid changing the argument in a pass by reference?

Any modifications to the argument value in a pass by reference can be avoided by using const keyword before ref, any attempt in changing the argument value in subroutine will lead to a compilation error. variables x and y are passed as an argument in the function call sum, changes to the argument x within the function, is visible outside.

Does passing the parameters by values affect the original variable?

Passing the parameters by values does not affect the original variable. Below is the example of Passing by Value: System.out.println (" Value (before change)="+p.a); System.out.println (" Value (after change)="+p.a); As we can see from the above output, the original values is not affected by the pass by value mechanism.


Video Answer


1 Answers

Closures close over variables, not values. Therefore, incrementing _variable can alter the behavior of the task that refers to it.

You can prevent this by making a local copy:

while (this._variable < 100)
{
    this._variable++;
    int local = _variable;
    var aTask = Task.Factory.StartNew(() =>
    {
        aList.add(local);
        update(this._savePoint);
    });
} 

Or you could pass the value to the task as state:

while (this._variable < 100)
{
    this._variable++;
    var aTask = Task.Factory.StartNew(object state =>
    {
        aList.add((int)state);
        update(this._savePoint);
    }, this._variable);
} 

These both work by copying the value of _variable to a new temporary variable. In the first case the local variable is defined inside the scope of the loop, so you get a new one for every iteration. In the second case, you make a copy of the value of _variable when you pass it to the Task as the state argument. If _variable were a reference type, these solutions wouldn't work; you'd have to perform a clone.

like image 124
Igby Largeman Avatar answered Oct 25 '22 23:10

Igby Largeman