I have ac# windows form where the user enters a set of parameters, and those parameters are then analyzed against a set of data to return a result. This analysis takes place on a background worker, by initializing a Backtest
object and iterating over a string list symbolParams
built from the values passed in through the form. When running the worker on one form, it works properly.
However, if I open up a second form, put in a new set of parameters, and run the worker on that form while the worker on the first form is still running, I get a "Collection was modified" error on the string list.
Seems as though the two background workers are affecting each other's symbolParams
list somehow. What's happening? How can this be fixed to allow multiple instances of this form to run this background worker simultaneously?
OptimizerForm.cs
public partial class OptimizerForm : Form
{
public static List<List<String>> backtestSymbolParams = new List<List<String>> { };
private void button15_Click(object sender, EventArgs e)
{
//Get parameters from the form
//Make a list for every param
string[] startEndTimes = textBox3.Text.Split(',');
string[] incrementPrices = textBox4.Text.Split(',');
string[] incrementSizes = textBox5.Text.Split(',');
string[] autoBalances = textBox6.Text.Split(',');
string[] hardStops = textBox7.Text.Split(',');
//Add every combo to symbol test params
for (int a = 0; a < startEndTimes.Length; a++)
{
for (int b = 0; b < incrementPrices.Length; b++)
{
for (int c = 0; c < incrementSizes.Length; c++)
{
for (int d = 0; d < autoBalances.Length; d++)
{
for (int f = 0; f < hardStops.Length; f++)
{
backtestSymbolParams.Add( new List<string> { symbol, startEndTimes[a].Split('-')[0], startEndTimes[a].Split('-')[1], incrementPrices[b],
incrementSizes[c], autoBalances[d], hardStops[f] });
}
}
}
}
}
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//Initialize Backtest instance with parameters gathered from the form
Backtest backtest = new Backtest(backtestSymbolParams, backtestSymbolDates, sender as BackgroundWorker);
TestResult testResult = new TestResult();
//Run the analysis
testResult = backtest.Run();
e.Result = testResult;
}
}
Backtest.cs
//Backtest Constructor
public Backtest(List<List<string>> _symbolParams, Dictionary<string, List<string>> _symbolDates, BackgroundWorker _bw)
{
symbolParams = _symbolParams;
symbolDates = _symbolDates;
bw = _bw;
}
//Backtest.Run()
public TestResult Run()
{
int symbolCount = 1;
//Collection modified exception occurs here
foreach (List<string> symbolParam in symbolParams) {
//do stuff
}
}
It seems like your symbolParams
variable in Backtest
class is static
, so simply mark it as private field for your class.
Also you have some issues with naming standards - method parameters should not start with _
, though fields should, so your constructor should looks like:
private List<List<String>> _symbolParams = new List<List<String>> { };
//Backtest Constructor
public Backtest(List<List<string>> symbolParams,
Dictionary<string, List<string>> symbolDates,
BackgroundWorker bw)
{
_symbolParams = symbolParams;
_symbolDates = symbolDates;
_bw = bw;
}
And, as far as I can see, you're using BackgroundWorker
as Task
so probably you should use TPL
itself, without old legacy classes
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.