Reputation: 8419
I am beginning with task library. I wrote simple code like
private void button1_Click(object sender, EventArgs e)
{
simpleMost();
}
string mesg;
void simpleMost()
{
mesg = "";
button1.Enabled = false;
Task t1 = new Task(delegate { makeResult(1); });
Task t2 = new Task(delegate { makeResult(2); });
Task t3 = new Task(delegate { makeResult(3); });
t1.Start();
t2.Start();
t3.Start();
t1.Wait();
t2.Wait();
t3.Wait();
richTextBox1.Text = mesg;
button1.Enabled = true;
}
void makeResult(int a)
{
mesg += "\nTask" + a;
}
I click my button1 again and again and get following outputs
1.
Task3
Task1
Task2
2.
Task1
Task2
Task3
3.
Task1
Task2
Task3
4.
Task2
Task3
5.
Task1
Task3
6.
Task1
Task2
In 4,5,6 cases why does not makeResult
work correctly. When I checked the Task states after wait statements they are found all completed but one of them misses the correct execution of function passed to it
Upvotes: 0
Views: 173
Reputation: 11
I think sometimes 2 tasks trying to access to "mesg" at the same time. Try it with a lock.
object syncObject = new object();
void makeResult(int a)
{
lock (syncObject)
{
mesg += "\nTask" + a;
}
}
Upvotes: 1
Reputation: 1500105
You have several tasks, each of which is modifying the same shared resource in a non-atomic way.
mesg += "\nTask" + a;
is effectively:
mesg = mesg + "\nTask" + a;
... so if one task reads mesg
, then another task writes a new value to it, then the first task will concatenate the strings using the old value, and write that back to the variable.
The simplest way to avoid this would be to use locking, so that only one thread can execute the modification statement at a time. It's not as elegant as it might be, but it should remove the race condition you currently have.
Upvotes: 2