0

I expect the variable in the loop to output 1,2,3 to my listbox below. But it outputs 2 2 2

what is wrong?

C# Code

  public partial class Tester : Form
    {

public int test = 1;


............................

 private void button1_Click(object sender, EventArgs e)
        {
            test++;

            for (int i = 0; i < 3; i++)
            {
                Task t = Task.Factory.StartNew(() =>
                {
                    System.Threading.Thread.Sleep(5000);                 


                }).ContinueWith(o =>
                {


                    listBox1.Items.Add(test);


                }, TaskScheduler.FromCurrentSynchronizationContext());

            }

        }
user1438082
  • 2,740
  • 10
  • 48
  • 82
  • 3
    'test++;' is executed once per button click. After it has been increased to 2, you enter your loop. This means the value will be 2 for all the threads. – Simon Oct 17 '14 at 08:03
  • 3
    Simon has the explanation for the current behavior. But it's likely once you move the "test++" into the loop, you'll run into the classic "captured wrong variable instance" problem. So be sure to read the reference provided by thumbmunkeys. – Peter Duniho Oct 17 '14 at 08:05
  • 1
    And of course, if you move it into the cycle (note that you have to declare the variable there as well - just copy the incremented value from the field, otherwise you'll get `4 4 4` instead :D), there's no guarantee you'll get `1 2 3` - you might get `2 1 3` instead, for example. If that's what you want, fine. If not, you might want to move the increment to the continuation - this will ensure you'll always get `1 2 3`. – Luaan Oct 17 '14 at 08:40

1 Answers1

1

If you want to know the sequence in which the Tasks are done you can use the following:

private void button1_Click(object sender, EventArgs e)
{

    for (int i = 0; i < 3; i++)
    {
        int tasknumber = test;
        Task t = Task.Factory.StartNew(() =>
        {
            System.Threading.Thread.Sleep(5000);
            return tasknumber;

        }).ContinueWith(o =>
        {
            listBox1.Items.Add(o.Result);
        }, TaskScheduler.FromCurrentSynchronizationContext());
        test++;
    }
}

With this code, the value of test is increased at the end of every loop. In the first Task, the tasknumber will be 1. In the second Task the tasknumber will be 2 etc. When the Task is done, the result will be passed to your ListBox.

You might also want to read this blog about StartNew.

Simon
  • 1,416
  • 1
  • 15
  • 24