0

Let's have 2 classes:

class MyClass
{
    public string str = "something";
    public int ind = 5;

    public MyClass()
    {

    }

    public void MyMethod()
    {
        //do something here
    }
}

And second one:

class ResultClass
{
    private string resultstring;
    private int resultint;

    public ResultClass(string resultstring, int resultint)
    {
        this.resultstring = resultstring;
        this.resultint = resultint;
    }

}

Now in the main form, let's say on form load we do:

private void Form1_Load(object sender, EventArgs e)
{
    List<MyClass> listMyClass = new List<MyClass>();
    List<ResultClass> listResultClass = new List<ResultClass>();
    MyClass itemMyClass1 = new MyClass();
    MyClass itemMyClass2 = new MyClass();
    listMyClass.Add(itemMyClass1);
    listMyClass.Add(itemMyClass2);
    for(int i = 0; i < listMyClass.Count; i++)
    {
        string s = listMyClass[i].str;
        int ind = listMyClass[i].ind;
        ResultClass result = new ResultClass(s, ind);
        listResultClass.Add(result);
    }
}

The problem:

I want to replace the for loop with tasks, so it can calculate all members of listResultClass simultaneously.

The best method so far I found is trying it like that:

private void Form1_Load(object sender, EventArgs e)
    {
        List<MyClass> listMyClass = new List<MyClass>();
        List<ResultClass> listResultClass = new List<ResultClass>();
        MyClass itemMyClass1 = new MyClass();
        MyClass itemMyClass2 = new MyClass();
        listMyClass.Add(itemMyClass1);
        listMyClass.Add(itemMyClass2);


        var tasks = listMyClass.Select(t => Task<ResultClass>.Factory.StartNew(() => TestTask(listMyClass))).ToArray();
        Task.WaitAll(tasks);
        listResultClass.AddRange(tasks.Select(task => task.Result));
    }

    private ResultClass TestTask(List<MyClass> listMyClass)
    {
        string s = listMyClass[i].str; //problem here
        int ind = listMyClass[i].ind; //and here
        ResultClass result = new ResultClass(s, ind);
        return result;
    }

But I have no idea how to steer the [i] value. I tried declaring an int and passing it to the TestTask, incrementing it at the end of the function, but it doesn't seem to work (probably because it's fired multiple times in the same time, making the int always 0).

How can I properly replace that loop?

0

2 Answers 2

1

It seems to me you just need to pass in t, since that is the item you want to process:

listMyClass.Select(t => Task.Run(() => TestTask(t)))

Or, you can get the index of the item in the Select and pass that one in the method:

listMyClass.Select
            ( (t, idx) => Task.Run
                          (() => TestTask(listMyClass, idx))
            )
Sign up to request clarification or add additional context in comments.

1 Comment

The second one with index worked perfectly for me, thanks!
1

Besides using the appropriate override of the Select method with an index, as already shown in the accepted answer, let me also suggest that you should not block the form's load event. Make it async

    private async void Form1_Load(object sender, EventArgs e)
    {

and add the await keyword inside

        var tasks = listMyClass.Select((t, i) => Task.Run(() => 
            TestTask(listMyClass, i)));
        listResultClass.AddRange(await Task.WhenAll(tasks));
    }

1 Comment

Thanks for improving the answer!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.