Lambda expression as ThreadStart strange behavior [duplicate] - c#

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C# - The foreach identifier and closures
From Eric Lippert’s blog: “don’t close over the loop variable”
I'm using a lambda expression as ThreadStart parameter, to run a method in a new thread using Thread class. This is my code:
delegate void del();
static void Do(int i)
{
Console.WriteLine(i);
}
static del CreateLoop(del Do)
{
return () =>
{
while (true)
{
Do();
Thread.Sleep(500);
}
};
}
static void Main(string[] args)
{
int n = 0;
var loop = CreateLoop(() => Do(n));
new Thread(() => loop()).Start();
Thread.Sleep(500);
n = 1;
}
And this is the output:
0
1
1
1
...
How is it possible?
Why if I change the value of my integer variable n, also changes the value of i (Do's parameter)?

You should make a different variable out of it, thus not changing the original value.
After all, all you're really doing is calling that same old 'function', the lambda expression passing the variable i over and over again, which indeed changes. It's nog like you're storing the initial value of the var i somewhere.

var loop = CreateLoop(() => Do(n));
This line is simply creating a new function and assigning it to a variable. This function, among other things, passes the value n to the Do function. But it's not calling the Do function, it's just creating a function which will, when executed, call the Do function.
You then start a new thread which calls the function, etc, but your new thread is still executing Do(n), passing the n variable to Do. That part doesn't change - you've created a function which references a particular place in memory (represented by the variable n) and continues to reference that place in memory even as you change the value which is stored there.
I believe the following would "fix" your code:
var loop = (int x) => () => CreateLoop(() => Do(x));
new Thread(loop(n)).Start();
This passes the value of n to the function represented by loop, but the loop function creates a new place in memory (represented by x) in which to store the value. This new place in memory is not affected by subsequent changes to n. That is to say, the function you've created does not directly reference the place in memory to which n is a pointer.

Related

cannot understand lambda expression output [duplicate]

This question already has answers here:
Captured variable in a loop in C#
(10 answers)
Closed last month.
I have this code and do not understand why the out put is 22! I am afraid it should be 01!
can anyone explain what happens? if the list store a method with a parameter, so the parameters should be 0 and 1 respectively!
List<Action> list = new List<Action>();
for (int i = 0; i < 2; i++)
{
list.Add(() => Console.Write(i));
}
foreach (var it in list)
{
it();
}
It is Closure (1, 2).
In your case Console.Write(i) will use value of i in the moment of action call. You firstly increment i in for loop then in second loop you call every action in the list. In the moment of call of every action i has value 2 - so, you get 22 as output.
To get expected result you should create local copy of i and use it:
for (int i = 0; i < 2; i++)
{
var temp = i;
list.Add(() => Console.Write(temp));
}
Addition to Roma Doskoch's anwser, another approach is to avoid for.
var list = Enumerable
.Range(0, 2)
.Select<int, Action>(i => () => Console.Write(i));
Closures capture variables, not values.
In your code, the closure captures the variable i, not whatever value happens to be stored in i on each iteration. When you invoke the action, the variable i has a value of 2 (because the loop has finished) and therefore 2 will be printed out twice.
In order to avoid this, as other answers already point out, you need to create a new variable every time around as a workaround to not being able to capture values; if you declare a new variable on every iteration then the result of capturing the variable is equivalent to capturing the value because you won't be changing it on the next iteration.

C# simple multithreading - why is it not producing the correct results? [duplicate]

This question already has answers here:
The foreach identifier and closures
(7 answers)
Closed 8 years ago.
can someone tell me why the below is not producing the correct results? It is giving me 1233 when I expected 0123.
public static readonly object locker = new object();
public static List<int> queue = new List<int>();
public static void calculate(int input)
{
Thread.Sleep(1000);
lock (locker)
{
queue.Add(input);
}
}
[TestMethod]
public void TestT()
{
int[] _intList = new int[] { 0, 1, 2, 3 };
List<Thread> _threadList = new List<Thread>();
foreach (int num in _intList)
{
Thread t = new Thread(() => calculate(num));
t.Start();
_threadList.Add(t);
}
foreach (Thread t in _threadList) { t.Join(); }
foreach (var t in queue)
{
Console.WriteLine(t);
}
}
When I change it to use a copy of the _intList variable instead, I get the correct results of 0123. Can someone tell me why this is happening? Is it being cached somewhere?
foreach (int num in _intList)
{
int testNum = num;
Thread t = new Thread(() => calculate(testNum));
t.Start();
_threadList.Add(t);
}
When you're passing a variable to a lambda expression it gets captured by the expression. So it's not a copy but that very variable you're getting. This is a common issue with foreach and delayed execution (multithreaded or not), since the foreach continues num is getting it's next value and if it does so because your thread gets to calculate, it's that value that will be calculated.
If you didn't multithread this but instead called the result of the lambda after the foreach what you would see would be 3 3 3 3 instead, in this case you're simply seeing them ofset by one because, most likely, the time it takes to start the thread is about the same as 1 iteration.
When you're making a copy of the variable that variable is declared within the scope of the foreach and it's a new variable each time, it's not getting changed to the next member and that variable is the one getting captured, giving you the correct result. This is the correct way to do this. The result you're getting isn't unexpected but not guaranteed either, you could be getting anything from 0 1 2 3 to 3 3 3 3 with the 1st method, the second method guarantees a correct output.

Where does a local variable get stored so that it's accessible from an asyc delegate? [duplicate]

What is a closure? Do we have them in .NET?
If they do exist in .NET, could you please provide a code snippet (preferably in C#) explaining it?
I have an article on this very topic. (It has lots of examples.)
In essence, a closure is a block of code which can be executed at a later time, but which maintains the environment in which it was first created - i.e. it can still use the local variables etc of the method which created it, even after that method has finished executing.
The general feature of closures is implemented in C# by anonymous methods and lambda expressions.
Here's an example using an anonymous method:
using System;
class Test
{
static void Main()
{
Action action = CreateAction();
action();
action();
}
static Action CreateAction()
{
int counter = 0;
return delegate
{
// Yes, it could be done in one statement;
// but it is clearer like this.
counter++;
Console.WriteLine("counter={0}", counter);
};
}
}
Output:
counter=1
counter=2
Here we can see that the action returned by CreateAction still has access to the counter variable, and can indeed increment it, even though CreateAction itself has finished.
If you are interested in seeing how C# implements Closure read "I know the answer (its 42) blog"
The compiler generates a class in the background to encapsulate the anoymous method and the variable j
[CompilerGenerated]
private sealed class <>c__DisplayClass2
{
public <>c__DisplayClass2();
public void <fillFunc>b__0()
{
Console.Write("{0} ", this.j);
}
public int j;
}
for the function:
static void fillFunc(int count) {
for (int i = 0; i < count; i++)
{
int j = i;
funcArr[i] = delegate()
{
Console.Write("{0} ", j);
};
}
}
Turning it into:
private static void fillFunc(int count)
{
for (int i = 0; i < count; i++)
{
Program.<>c__DisplayClass1 class1 = new Program.<>c__DisplayClass1();
class1.j = i;
Program.funcArr[i] = new Func(class1.<fillFunc>b__0);
}
}
Closures are functional values that hold onto variable values from their original scope. C# can use them in the form of anonymous delegates.
For a very simple example, take this C# code:
delegate int testDel();
static void Main(string[] args)
{
int foo = 4;
testDel myClosure = delegate()
{
return foo;
};
int bar = myClosure();
}
At the end of it, bar will be set to 4, and the myClosure delegate can be passed around to be used elsewhere in the program.
Closures can be used for a lot of useful things, like delayed execution or to simplify interfaces - LINQ is mainly built using closures. The most immediate way it comes in handy for most developers is adding event handlers to dynamically created controls - you can use closures to add behavior when the control is instantiated, rather than storing data elsewhere.
Func<int, int> GetMultiplier(int a)
{
return delegate(int b) { return a * b; } ;
}
//...
var fn2 = GetMultiplier(2);
var fn3 = GetMultiplier(3);
Console.WriteLine(fn2(2)); //outputs 4
Console.WriteLine(fn2(3)); //outputs 6
Console.WriteLine(fn3(2)); //outputs 6
Console.WriteLine(fn3(3)); //outputs 9
A closure is an anonymous function passed outside of the function in which it is created.
It maintains any variables from the function in which it is created that it uses.
A closure is when a function is defined inside another function (or method) and it uses the variables from the parent method. This use of variables which are located in a method and wrapped in a function defined within it, is called a closure.
Mark Seemann has some interesting examples of closures in his blog post where he does a parallel between oop and functional programming.
And to make it more detailed
var workingDirectory = new DirectoryInfo(Environment.CurrentDirectory);//when this variable
Func<int, string> read = id =>
{
var path = Path.Combine(workingDirectory.FullName, id + ".txt");//is used inside this function
return File.ReadAllText(path);
};//the entire process is called a closure.
Here is a contrived example for C# which I created from similar code in JavaScript:
public delegate T Iterator<T>() where T : class;
public Iterator<T> CreateIterator<T>(IList<T> x) where T : class
{
var i = 0;
return delegate { return (i < x.Count) ? x[i++] : null; };
}
So, here is some code that shows how to use the above code...
var iterator = CreateIterator(new string[3] { "Foo", "Bar", "Baz"});
// So, although CreateIterator() has been called and returned, the variable
// "i" within CreateIterator() will live on because of a closure created
// within that method, so that every time the anonymous delegate returned
// from it is called (by calling iterator()) it's value will increment.
string currentString;
currentString = iterator(); // currentString is now "Foo"
currentString = iterator(); // currentString is now "Bar"
currentString = iterator(); // currentString is now "Baz"
currentString = iterator(); // currentString is now null
Hope that is somewhat helpful.
Closures are chunks of code that reference a variable outside themselves, (from below them on the stack), that might be called or executed later, (like when an event or delegate is defined, and could get called at some indefinite future point in time)... Because the outside variable that the chunk of code references may gone out of scope (and would otherwise have been lost), the fact that it is referenced by the chunk of code (called a closure) tells the runtime to "hold" that variable in scope until it is no longer needed by the closure chunk of code...
Basically closure is a block of code that you can pass as an argument to a function. C# supports closures in form of anonymous delegates.
Here is a simple example:
List.Find method can accept and execute piece of code (closure) to find list's item.
// Passing a block of code as a function argument
List<int> ints = new List<int> {1, 2, 3};
ints.Find(delegate(int value) { return value == 1; });
Using C#3.0 syntax we can write this as:
ints.Find(value => value == 1);
If you write an inline anonymous method (C#2) or (preferably) a Lambda expression (C#3+), an actual method is still being created. If that code is using an outer-scope local variable - you still need to pass that variable to the method somehow.
e.g. take this Linq Where clause (which is a simple extension method which passes a lambda expression):
var i = 0;
var items = new List<string>
{
"Hello","World"
};
var filtered = items.Where(x =>
// this is a predicate, i.e. a Func<T, bool> written as a lambda expression
// which is still a method actually being created for you in compile time
{
i++;
return true;
});
if you want to use i in that lambda expression, you have to pass it to that created method.
So the first question that arises is: should it be passed by value or reference?
Pass by reference is (I guess) more preferable as you get read/write access to that variable (and this is what C# does; I guess the team in Microsoft weighed the pros and cons and went with by-reference; According to Jon Skeet's article, Java went with by-value).
But then another question arises: Where to allocate that i?
Should it actually/naturally be allocated on the stack?
Well, if you allocate it on the stack and pass it by reference, there can be situations where it outlives it's own stack frame. Take this example:
static void Main(string[] args)
{
Outlive();
var list = whereItems.ToList();
Console.ReadLine();
}
static IEnumerable<string> whereItems;
static void Outlive()
{
var i = 0;
var items = new List<string>
{
"Hello","World"
};
whereItems = items.Where(x =>
{
i++;
Console.WriteLine(i);
return true;
});
}
The lambda expression (in the Where clause) again creates a method which refers to an i. If i is allocated on the stack of Outlive, then by the time you enumerate the whereItems, the i used in the generated method will point to the i of Outlive, i.e. to a place in the stack that is no longer accessible.
Ok, so we need it on the heap then.
So what the C# compiler does to support this inline anonymous/lambda, is use what is called "Closures": It creates a class on the Heap called (rather poorly) DisplayClass which has a field containing the i, and the Function that actually uses it.
Something that would be equivalent to this (you can see the IL generated using ILSpy or ILDASM):
class <>c_DisplayClass1
{
public int i;
public bool <GetFunc>b__0()
{
this.i++;
Console.WriteLine(i);
return true;
}
}
It instantiates that class in your local scope, and replaces any code relating to i or the lambda expression with that closure instance. So - anytime you are using the i in your "local scope" code where i was defined, you are actually using that DisplayClass instance field.
So if I would change the "local" i in the main method, it will actually change _DisplayClass.i ;
i.e.
var i = 0;
var items = new List<string>
{
"Hello","World"
};
var filtered = items.Where(x =>
{
i++;
return true;
});
filtered.ToList(); // will enumerate filtered, i = 2
i = 10; // i will be overwriten with 10
filtered.ToList(); // will enumerate filtered again, i = 12
Console.WriteLine(i); // should print out 12
it will print out 12, as "i = 10" goes to that dispalyclass field and changes it just before the 2nd enumeration.
A good source on the topic is this Bart De Smet Pluralsight module (requires registration) (also ignore his erroneous use of the term "Hoisting" - what (I think) he means is that the local variable (i.e. i) is changed to refer to the the new DisplayClass field).
In other news, there seems to be some misconception that "Closures" are related to loops - as I understand "Closures" are NOT a concept related to loops, but rather to anonymous methods / lambda expressions use of local scoped variables - although some trick questions use loops to demonstrate it.
A closure aims to simplify functional thinking, and it allows the runtime to manage
state, releasing extra complexity for the developer. A closure is a first-class function
with free variables that are bound in the lexical environment. Behind these buzzwords
hides a simple concept: closures are a more convenient way to give functions access
to local state and to pass data into background operations. They are special functions
that carry an implicit binding to all the nonlocal variables (also called free variables or
up-values) referenced. Moreover, a closure allows a function to access one or more nonlocal variables even when invoked outside its immediate lexical scope, and the body
of this special function can transport these free variables as a single entity, defined in
its enclosing scope. More importantly, a closure encapsulates behavior and passes it
around like any other object, granting access to the context in which the closure was
created, reading, and updating these values.
Just out of the blue,a simple and more understanding answer from the book C# 7.0 nutshell.
Pre-requisit you should know :A lambda expression can reference the local variables and parameters of the method
in which it’s defined (outer variables).
static void Main()
{
int factor = 2;
//Here factor is the variable that takes part in lambda expression.
Func<int, int> multiplier = n => n * factor;
Console.WriteLine (multiplier (3)); // 6
}
Real part:Outer variables referenced by a lambda expression are called captured variables. A lambda expression that captures variables is called a closure.
Last Point to be noted:Captured variables are evaluated when the delegate is actually invoked, not when the variables were captured:
int factor = 2;
Func<int, int> multiplier = n => n * factor;
factor = 10;
Console.WriteLine (multiplier (3)); // 30
A closure is a function, defined within a function, that can access the local variables of it as well as its parent.
public string GetByName(string name)
{
List<things> theThings = new List<things>();
return theThings.Find<things>(t => t.Name == name)[0];
}
so the function inside the find method.
t => t.Name == name
can access the variables inside its scope, t, and the variable name which is in its parents scope. Even though it is executed by the find method as a delegate, from another scope all together.

How is a captured variable simultaneously exposed to multiple threads of execution?

In C# spec 4.0 section 7.15.5.1:
Note that unlike an uncaptured variable, a captured local variable can
be simulataneously exposed to multiple threads of execution.
What exactly does it mean by "multiple threads of execution"? Does this mean multiple threads, multiple execution paths or something else?
E.G.
private static void Main(string[] args)
{
Action[] result = new Action[3];
int x;
for (int i = 0; i < 3; i++)
{
//int x = i * 2 + 1;//this behaves more intuitively. Outputs 1,3,5
x = i*2 + 1;
result[i] = () => { Console.WriteLine(x); };
}
foreach (var a in result)
{
a(); //outputs 5 each time
}
//OR...
int y = 1;
Action one = new Action(() =>
{
Console.WriteLine(y);//Outputs 1
y = 2;
});
Action two = new Action(() =>
{
Console.WriteLine(y);//Outputs 2. Working with same Y
});
var t1 = Task.Factory.StartNew(one);
t1.Wait();
Task.Factory.StartNew(two);
Console.Read();
}
Here x exhibits different behavior based upon where x is declared. In the case of y the same variable is captured and used by multiple threads, but IMO this behavior is intuitive.
What are they referring to?
"Multiple threads of execution" just means multiple threads; i.e., multiple threads that are executing concurrently. If a particular variable is exposed to multiple threads, any of those threads can read and write that variable's value.
This is potentially dangerous and should be avoided whenever possible. One possibility to avoid this, if your scenario allows, is to create local copies of variables in your tasks' methods.
If you modify the second part of your code a little:
int y = 1;
Action one = new Action(() =>
{
Console.WriteLine(y);//Outputs 1
y = 2;
});
Action two = new Action(() =>
{
Console.WriteLine(y);//Outputs 2. Working with same Y
y = 1;
});
var t1 = Task.Factory.StartNew(one);
t1 = Task.Factory.StartNew(two);
t1.Wait();
t1 = Task.Factory.StartNew(one);
t1.Wait();
t1 = Task.Factory.StartNew(two);
Console.Read();
Run it a few times or put it in a loop. It will output different, seemingly random, results, e.g. 1 1 1 2 or 1 2 1 2.
Multiple threads are accessing the same variable and getting and setting it simultaneously, which may give unexpected results.
Refer to the link below.
A reference to the outer variable n is said to be captured when the delegate is created. Unlike local variables, the lifetime of a captured variable extends until the delegates that reference the anonymous methods are eligible for garbage collection.
In other words the variable's memory location is captured when the method is created and then shared to that method. Just like if a thread had access to that variable minus the anonymous method. There is a compiler warning that will occur in some cases that it will suggest you move to a local temp variable to not cause unintended consequences.
MSDN Anonymous Methods

Action delegate uses the last values of variables declared outside foreach loop [duplicate]

This question already has answers here:
Captured variable in a loop in C#
(10 answers)
Closed 2 years ago.
I have this piece of code:
int i = 0;
foreach(var tile in lib.dic.Values)
{
var ii = i;
var t = tile;
Button b = new Button( () = > { MainStatic.tile = t; } );
Checkbox c = new Checkbox( () = > { lib.arr[ii].b = !lib.arr[ii].b; } );
i++;
}
While the above code works as it should, this piece below:
int i = 0;
foreach(var tile in lib.dic.Values)
{
Button b = new Button( () = > { MainStatic.tile = tile; } );
Checkbox c = new Checkbox( () = > { lib.arr[i].b = !lib.arr[i].b; } );
i++;
}
…will always execute the delegates with the last values of i and tile variables. Why does this happen, and why do I have to make a local copy of those vars, especially non-reference type int i?
Known "issue", please check Eric's blog Closures, captured variables.
Microsof decided to go for a breaking change, and fix it in C# 5.
This is expected: when you make a lambda, compiler creates a closure. It will capture the value of a temporary variable in there, but it would not capture the value of loop variables and other variables that change after creation of the lambda.
The core of the issue is that the delegate creation and execution times are different. The delegate object is created while the loop is running, but it is called well after the loop has completed. At the time the delegate is called, the loop variable has the value that it reached at the time the loop has completed, resulting in the effect that you see (the value does not change, and you see the last value from the loop).
Forgetting to create a temporary variable for use in closures is a mistake so common that popular code analyzers (e.g. ReSharper) warn you about it.
You cannot use loop variables like this because by the time the delegate is executed the loop variable will likely be in its final (end of loop) state as it uses the value of the variable at the time the delete is executed, not created.
You need to make a local copy of the variable to get this to work:
int i = 0;
foreach(var tile in lib.dic.Values)
{
var tileForClosure = tile;
var iForClosure = i;
Button b = new Button( () = > { MainStatic.tile = tileForClosure ; } );
Checkbox c = new Checkbox( () = > { lib.arr[iForClosure].b = !lib.arr[iForClosure].b; } );
i++;
}
By creating a local copy on each loop the value does not change and so your delegate will use the value that you expect.

Categories

Resources