The cause of this error is that the backgroundworker runs in its own thread. Your UI including the listView1 is running in another (probably the main thread of your application). retrieving properties from object in another thread is allowed, but changing them is not.
The solution is to get into the UI thread first and then change the selected item. When using threads in a Windows form, this can be done by calling the Invoke statement. But there is an easier alternative if you are using the BackgroundWorker (although in more complex situations one might prefer to use the Invoke).
The ProgressChanged event is handled in the UI thread. This is were you want to update the listView1. The ReportProgress has two signatures:
ReportProgress(int);
ReportProgress(int, object);
The latter has a extra parameter which you can use to send any object (including custom classes). You can uses this to pass the value j to the UI thread. The ProgressChangedEventArgs.UserState will contain the value of j.
private void StartButton_Click(object sender, EventArgs e)
{
int currentSelected = 0;
for (i = 0; i < ListView1.Items.Count; i++)
{
if (ListView1.Items[i].Selected == true)
{
currentSelected = i;
break;
}
}
Worker1.RunAsync(new Tuple<int, int>(count, currentSelected));
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
int count = 0;
int sum = 0;
int currentSelected = 0;
if (e.Argument is Tuple<int, int>)
{
count = (e.Argument as Tuple<int, int>).Item1;
currentSelected = (e.Argument as Tuple<int, int>).Item2;
}
bool isCurrentSet = false;
for (int i = 0, j = 0; i < listView1.Items.Count && j < listView1.Items.Count; j++)
{
if (!isCurrentSet)
{
j = currentSelected;
isCurrentSet = true;
}
backgroundWorker1.ReportProgress(i * 100 / count, j);
Thread.Sleep(2000);
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
break;
}
sum += i;
backgroundWorker1.ReportProgress(i * 100 / count);
Thread.Sleep(2000);
}
e.Result = sum;
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
if (e.UserState != null)
{
int j = (int)e.UserState;
if (j != 0)
{
listView1.Items[j - 1].Selected = false;
}
listView1.Items[j].Selected = true;
}
}
This will probably solve the error you encountered.
You might need to check the progress reporting too. The progress remained at 0 because the i value wasn't increased.