Sami
Sami

Reputation: 8419

Processing on shared variable by parallel tasks

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

Answers (2)

SoBaKa
SoBaKa

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

Jon Skeet
Jon Skeet

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

Related Questions