This is from Joseph Albahari’s excellent C# 5.0 in a Nutshell book
In one of his chapters, he mentions a race-condition in this code block ..my guess is it’s meant to be pretty self-evident, as he didn’t bother to specify where it was but running the code multiple times I was unable to produce the said-race condition
_button.Click += (sender, args) =>
{
_button.IsEnabled = false;
Task.Run (() => Go());
};
void Go()
{
for (int i = 1; i < 5; i++)
{
int result = GetPrimesCount (i * 1000000, 1000000);
Dispatcher.BeginInvoke (new Action (() =>
_results.Text += result + " primes between " + (i*1000000) + " and " +
((i+1)*1000000-1) + Environment.NewLine));
}
Dispatcher.BeginInvoke (new Action (() => _button.IsEnabled = true));
}
I don’t agree with @Serge’s answer. You don’t even need multiple threads to see the problem. Try to run your code in its original form and notice the output. For me it’s the following and is sometimes random (I fixed the first value):
Notice the last 2 values. They’re all the same, but they should depend on
i. The problem is not that the operation is not atomic, because the GUI thread will execute the actions sequentially anyway.The reason for this occurring is that the lambda function passed to
BeginInvoketakes the value ofiat the moment of execution, not at the moment of initialization, so they will all see the last value ofiby the time they get executed. The solution is to explicitly passias a parameter to the lambda like so: