1

我首先有这个代码的构造函数和按钮点击事件:

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());

调用的目标已抛出异常

通过向后台工作人员完成事件报告来解决它:

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);
            }
        }

工作刚刚好。

4

1 回答 1

2

您已经解决了这个问题(正确地,这应该在 Completed 事件中完成)。

剩下的就是一个解释:

您正在iAction lambda 中使用 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)));
    }
}
于 2012-08-25T05:39:22.247 回答