Janushoff Janushoff - 1 year ago 56
C# Question

Replacing for loop with Tasks - passing variable

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?

Answer Source

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))
            )
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download