I have this code first the constructor and button click event:
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using System.IO;
using System.Collections;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
DirectoryInfo dirinf = new DirectoryInfo(@"C:\");
List<FileSystemInfo> fsi = new List<FileSystemInfo>();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
button1.Enabled = false;
}
Then i have a search function and a backgroundowrker DoWork event:
public void Search(string strExtension,
DirectoryInfo di,
List<FileSystemInfo> pResult)
{
try
{
foreach (FileInfo fi in di.GetFiles())
{
if (InvokeRequired)
{
BeginInvoke(new Action(() => label2.Text = fi.Name));
}
if (fi.Name == "MessageLog.xsl")
{
foreach (FileInfo fii in di.GetFiles())
{
if (fii.Extension == strExtension)
pResult.Add(fii);
}
if (InvokeRequired)
{
BeginInvoke(new Action(() => textBox1.AppendText("Number Of History Files Found: ===> " + pResult.Count.ToString() + Environment.NewLine)));
}
}
}
foreach (DirectoryInfo diChild in di.GetDirectories())
Search(strExtension, diChild, pResult);
}
catch (Exception e)
{
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
Search(".xml", dirinf, fsi);
for (int i = 0; i < fsi.Count; i++)
{
if (InvokeRequired)
{
BeginInvoke(new Action(() => textBox1.AppendText(fsi[i - 1].FullName + Environment.NewLine)));
}
}
}
When its getting to the part in the DoWork event:
for (int i = 0; i < fsi.Count; i++)
{
if (InvokeRequired)
{
BeginInvoke(new Action(() => textBox1.AppendText(fsi[i - 1].FullName + Environment.NewLine)));
}
}
After one or two itertions its throwing exception in the Program.cs on the line:
Application.Run(new Form1());
Exception has been thrown by the target of an invocation
Solved it by reporting to the backgroundworker completed event:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
Search(".xml", dirinf, fsi);
backgroundWorker1.ReportProgress(100);
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
for (int i = 0; i < fsi.Count; i++)
{
textBox1.AppendText(fsi[i].FullName + Environment.NewLine);
}
}
Working just good.
You have already solved the issue (correctly, this should be done in the Completed event).
What remains is an explanation:
You are using the variable
i, that is local to the DoWork method, inside the Action lambda. This means all code uses 1 shared (boxed) version of the variable. It’s called ‘closing over the loop var’.The symptoms fit: the lambdas are executed async, when the 2nd or 3rd starts executing the main loop has already made
i == fsi.Count. The (inner) exception should be “Index out of range”.It can be fixed this way: