我首先使用此代码构造函数和按钮单击事件:
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;
}
然后我有一个搜索功能和一个backgroundowrker DoWork活动:
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)));
}
}
}
当它进入DoWork活动的部分时:
for (int i = 0; i < fsi.Count; i++)
{
if (InvokeRequired)
{
BeginInvoke(new Action(() => textBox1.AppendText(fsi[i - 1].FullName + Environment.NewLine)));
}
}
在一行或两次迭代之后,它在Program.cs中抛出异常:
Application.Run(new Form1());
调用目标抛出了异常
通过向backgroundworker完成的事件报告来解决它:
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);
}
}
工作得很好。
答案 0 :(得分:2)
您已经解决了问题(正确地说,这应该在Completed事件中完成)。
剩下的是一个解释:
您正在使用Action lambda中的变量i
,它是DoWork方法的本地变量。这意味着所有代码都使用1个共享(盒装)版本的变量。它被称为“关闭循环变量”。
症状适合:lambdas执行异步,当第二个或第三个开始执行主循环时已经i == fsi.Count
。 (内部)异常应为“索引超出范围”。
for (int i = 0; i < fsi.Count; i++)
{
if (InvokeRequired)
{
BeginInvoke(new Action(() =>
textBox1.AppendText(fsi[i - 1].FullName // captured 'i'
+ Environment.NewLine)));
}
}
可以通过这种方式修复:
for (int i = 0; i < fsi.Count; i++)
{
if (InvokeRequired)
{
int iCopy = i; // 1 instance per loop
BeginInvoke(new Action(() =>
textBox1.AppendText(fsi[iCopy - 1].FullName
+ Environment.NewLine)));
}
}