0

I will rephrase the question. This is a simplified code of what i want to do. the Labels will be dynamic and will have to be passed in the function. The function startCount() will do a lot more and i want to thread out each one to save time. The code works fine (counts and changes the value for now).
I also need to do other functions when all Tasks are done.
I took out the extra Task in the startCount() function.

As to the other examples, I am not using await and with the removal ot Task in the startCount() now the program freezes.

private void Form1_Load(object sender, EventArgs e)
{
    strCounter.Add("66");   //Simulate reading file 
    strCounter.Add("69");

    labels = new Label[strCounter.Count];   //Create the Array of Labels

    for (int i = 0; i < strCounter.Count; i++)
    {
        labels[i] = new Label();            //Create label and add it to Form
        labels[i].Size = new Size(30, 15);
        labels[i].Location = new Point(10, 50 + (i * 20));
        labels[i].Text = strCounter[i];
        this.Controls.Add(labels[i]);
    }
}

private void button1_Click(object sender, EventArgs e)
{
    List<Task> tasks = new List<Task>();    //Create List of Tasks

    for (int i = 0; i < strCounter.Count; i++)
    {
        int ii = i;
        Task LastTask = new Task(() => startCount(i.ToString(), labels[ii]));

        tasks.Add(LastTask);
        tasks[i].ConfigureAwait(false);
        tasks[i].Start();

    }
    // This line will cause the entire program to freeze.
    // If i comment out, the program works fine.
    Task.WaitAll(tasks.ToArray());

    MessageBox.Show("Should be After");
}

private void startCount(string strCount, Label lbl)
{
    for (int i = 0; i < 100; i++)
    {
        int count = int.Parse(lbl.Text) + 1;    //Add 1
        writeLabelBox(lbl, count.ToString());   //Use Invoke function
        Thread.Sleep(20);
    }
}

public void writeLabelBox(Label l, string strA)
{
    this.Invoke((MethodInvoker)delegate()
    {
        l.Text = strA;
    });
}
Chava
  • 1
  • 1
  • Maybe all tasks were finished? – Jeroen Heier Dec 31 '17 at 08:22
  • This is horrible, you are creating tasks for no reason. You are going to starve the threadpool. – Erik Philips Dec 31 '17 at 08:33
  • You should not need to do `new Task` or `Task.Start()`. These are needed for advanced features that you aren't using and complicate things. Use `Task.Run()` instead. Also what @ErikPhilips said -- you're parallelizing things at too fine-grained a level and it will go slower. So, rethink your strategy if it's a real app. – Cory Nelson Dec 31 '17 at 08:42
  • There are lots of things wrong with your code, but the main thing is that you've wrapped the task you really want to wait on, in a different task that completes immediately, because that different task is doing nothing more than creating the task you really want to wait on (which of course, takes very little time at all). See marked duplicates for several of the literally thousand or more similar questions on Stack Overflow, which we've already answered. – Peter Duniho Dec 31 '17 at 08:59
  • i really simplified the code to what it is really going to do. The label is one part of many and did not want extra code for the problem. And yes i do want to thread this out. The thread will give the UI time to update, and it works fine if i comment out **Task.WaitAll(tasks.ToArray());**. – Chava Dec 31 '17 at 14:38

1 Answers1

2

You are already creating a task inside the function and returning it. so you don't need to create another task.
You are simply waiting on the wrong tasks.

Change this line:

Task LastTask = new Task(() => startCount(i.ToString(), labels[ii]));

To This:

Task LastTask = startCount(i.ToString(), labels[ii]);

And drop the tasks[i].Start(); since it's already started in the function.

Or leave it as it is but don't create a Task in the function.

In any case, why create a task for each label and not just one task for the whole loop?

Ofir Winegarten
  • 9,215
  • 2
  • 21
  • 27