1

Forgive me if this is simple. I come from the Embedded RToS world and have learnt c# for just for the purpose of test equipment for production. I think I have solved all the obvious issues already, just the tasks are not acting as expected.

I have a test jig with 10 serial ports and other things attached and a very basic windows forms UI with 10 list box's that need to all run simultaneously. I have cut the code down to just what is needed for the demo of the problem (no serial ports etc)

I am unable to get 10 listbox's (or textboxs) to update from 10 tasks properly. I can easily do one at a time, even 5 works, but 10 and it does not work.

I was getting exception out of range as it somehow gets passed a 10, but I only pass 0-9 so I reduced the task count to 9 for now until I understand the fundamental issue(s).

private void buttonStart_Click(object sender, EventArgs e)
{
    Task.Factory.StartNew(() => PTT.ProductionTest());
}

This is the task from the PTT class, it will manage and monitor the 10 tasks so the UI is still responsive

    public static void ProductionTest()
    {
        //Somewhere to store the tasks
        List<Task> TestSlotTasks = new List<Task>();
        //Create the tasks for each of the test slots
        for (int i = 0; i != 9; ++i)
        {
            TestSlotTasks.Add(Task.Factory.StartNew(() => new PTT().TestSlot(i)));
            Program.ListBoxAddLine(string.Format("CALL[{0}]: task start/stop test", i), System.Drawing.Color.LawnGreen, i);
        }
        Task.WaitAll(TestSlotTasks.ToArray());
    }

This is supposed to be a non static program so I can create multiple instances (so I can run it many times without issue, that is my intention anyway, right?)

    private void TestSlot(int slot)
    {
        for (var z = 0; z != 10; ++z)
        {
            Program.ListBoxAddLine(string.Format("PTT[{0}]: task start/stop test", slot), System.Drawing.Color.LawnGreen, slot);
        }
    }

This is the invoke method i use to update the listBox. The list box is in a generic list something like this

//ListBoxs.Add(listBoxSlot1); //Done for each of the 10 list box's to put in a list

    //This is the method that will add a line to the main text box and to the log file
    public static void ListBoxAddLine(string TextToAdd, System.Drawing.Color textColor, int slot)
    {
        //Update the list box on the main screen
        if (mainForm != null)
        {
            if (FormPTT.ListBoxs[slot].InvokeRequired)
            {
                FormPTT.ListBoxs[slot].Invoke((MethodInvoker)delegate ()
                {
                    FormPTT.ListBoxs[slot].ForeColor = textColor;
                    FormPTT.ListBoxs[slot].TopIndex = FormPTT.ListBoxs[slot].Items.Add(TextToAdd);
                });
            }
            else
            {
                FormPTT.ListBoxs[slot].ForeColor = textColor;
                FormPTT.ListBoxs[slot].TopIndex = FormPTT.ListBoxs[slot].Items.Add(TextToAdd);
            }
        }
    }

The output I get is pretty random if i go above 5 or 6 list box's for this example.

Using the above code, I get this

output in the list box's, ignore the other stuff

So its all ok up until slot 8, its shows the Call[7] task start/stop but nothing from the task call and 9 and 10 are ok, but I dont call it 10 times, so how is 10 getting updated? I dont pass 10? and where is 8's PTT[7]... output?

I assume I am just not understanding a few things about tasks...

  • 1
    Could you add to the tags the UI tech you're using please? Winforms or WPF? – bic Nov 10 '17 at 21:05
  • In ProductionTest for loop do 'int tmp = i;' and pass that 'tmp' instead of 'i' to new PTT().TestSlot() call. – Evk Nov 10 '17 at 21:09
  • You have a lot of issues in your code. First of them is modified closure on loop variable. – Hamlet Hakobyan Nov 10 '17 at 21:10
  • https://stackoverflow.com/questions/127188/could-you-explain-sta-and-mta – bic Nov 10 '17 at 21:12
  • "I assume I am just not understanding a few things about tasks...", Tasks are essentially managed jobs being run on the ThreadPool. You will need to invoke the UI thread to make changes to the UI from a background thread or task in this case. – bic Nov 10 '17 at 21:17
  • Ok, so my issue with that code was that the for loop pass's like a reference, which in C code this would work, but it seems in c# calling function(i) pass's the actual reference for the int, in C it would give the function a copy of that int so I cahnged it to this – Carl Norman Nov 11 '17 at 00:08

0 Answers0