线程方法超出 ProgressChanged

Thread Method Outrunning ProgressChanged

我有一个简单的应用程序,它通过 BackgroundWorker 在单独的线程中执行一个函数,并且 运行 遇到了问题。我正在收集一个字符串值数组,并通过 ReportProgress 方法将其传回我的 ProgressChanged 事件,我 运行 遇到了一个问题,线程继续运行并且速度如此之快,结果 运行s ProgressChanged 事件并在将值添加到网格之前覆盖这些值。下面是我的代码...

按钮单击事件触发我的线程...

private void LoadButton_Click(object sender, EventArgs e)
{
    if (!string.IsNullOrEmpty(WorkingPathTextBox.Text))
    {
        this.dataGridView1.Rows.Clear();
        this.progressBar1.Visible = true;
        this.LoadButton.Visible = false;
        this.BrowseButton.Enabled = false;
        this.WorkingPathTextBox.Enabled = false;
        this.CancelBtn.Visible = true;
        this.ProcessingLabel.Visible = true;

        beginTime = DateTime.Now;

        WorkflowCleanup wc = new WorkflowCleanup();
        wc.WorkflowPath = this.WorkingPathTextBox.Text; 
        backgroundWorker1.RunWorkerAsync(wc);
    }
}

在 DoWork 中,它会加载 class 我的作品所在的位置...

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    System.ComponentModel.BackgroundWorker worker;
    worker = (System.ComponentModel.BackgroundWorker)sender;

    // Get the Words object and call the main method.
    WorkflowCleanup wc = (WorkflowCleanup)e.Argument;
    wc.LoadAssemblies(worker, e);
    wc.LoadDataDefinitions(worker, e);
    wc.LoadDataDefinitionsDirty(worker, e);
    wc.LoadProcesses(worker, e);
    wc.LoadProcessesDirty(worker, e);
    wc.LoadWorkflows(worker, e);

    // wc.UpdateWorkflows(worker, e);
}

WorkflowCleanup class...ReportProgress 卡在 try/catch 的中间,因为我无法弄清楚是什么导致了问题。所以,我在尝试中移动了它,甚至不得不添加一个 Thread.Sleep(100) 来减慢进程,以便为 ProgressChanged 事件提供足够的时间来添加我在它之前传递给网格的数据行覆盖...

namespace WorkflowMaintenance
{
    public class WorkflowCleanup
    {
        private int errorCount = 0;
        private int fixCount = 0;

        public class Workflow 
        { 
            // code truncated
        }
        public class WorkflowAssembly 
        {
            // code truncated
        }

        public class DataDefinition
        {
            // code truncated
        }

        public class CurrentState
        {
            public int Percentage;
            public string StateString;
            public List<string[]> ProcessResults;
            public string[] Result;
            public int ErrorCount;
            public int FixCount;
        }

        public void LoadAssemblies(System.ComponentModel.BackgroundWorker worker, System.ComponentModel.DoWorkEventArgs e)
        {
            CurrentState state = new CurrentState();
            fixCount = 0;
            errorCount = 0;

            string[] asmbfiles = System.IO.Directory.GetFiles(WorkflowPath + "\Assemblies", "*.asmb", System.IO.SearchOption.AllDirectories);

            int asmbIndex = 0;

            Assemblies = new List<WorkflowAssembly>();

            // Assemblies (NEW)
            foreach (string asmb in asmbfiles)
            {
                if (worker.CancellationPending)
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    //results = new List<string[]>();

                    asmbIndex += 1;
                    int percentage = (asmbIndex * 100) / asmbfiles.Length;
                    state.StateString = string.Format("Loading Assemblies... {0}%", percentage);
                    state.Percentage = percentage;

                    try
                    {
                        XDocument xdoc = XDocument.Load(asmb);
                        XElement asmbElement = xdoc.Descendants(wf + "assembly").First();
                        XElement asmbTypes = asmbElement.Element(wf + "types");
                        string asmbid = asmbElement.Attribute("id").Value;
                        string asmbname = asmbElement.Element(wf + "name").Value;
                        string asmbpath = asmbElement.Element(wf + "assemblyPath").Value;

                        Assemblies.Add(new WorkflowAssembly() { ID = asmbid, Name = asmbname, FileName = asmb, AssemblyPath = asmbpath, Types = asmbTypes });
                        //results.Add(new string[] { "SUCCESS", "ASSEMBLY PROCESSED SUCCESSFULLY", asmbname, asmbid, null, asmb });
                        state.Result = new string[] { "SUCCESS", "ASSEMBLY PROCESSED SUCCESSFULLY", asmbname, asmbid, null, asmb };
                        fixCount += 1;

                        //if (results != null && results.Count > 0)
                        //{
                        //    state.ProcessResult = results;
                        //}

                        state.FixCount = fixCount;
                        state.ErrorCount = errorCount;

                        worker.ReportProgress(percentage, state);
                        Thread.Sleep(100);
                    }
                    catch (Exception)
                    {
                        // need to report the exception...
                        errorCount += 1;
                    }
                    finally
                    {
                        //if (results != null && results.Count > 0)
                        //{
                        //    state.ProcessResult = results;
                        //}

                        //state.FixCount = fixCount;
                        //state.ErrorCount = errorCount;

                        //worker.ReportProgress(percentage, state);
                    }
            }
        }
    }
    }
}

ProgressChanged 事件...

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // This method runs on the main thread.
    WorkflowCleanup.CurrentState state = (WorkflowCleanup.CurrentState)e.UserState;

    this.progressBar1.Value = state.Percentage;
    this.ProcessingLabel.Text = state.StateString;
    this.errorLabel.Text = string.Format("Errors: {0}", state.ErrorCount);
    this.fixLabel.Text = string.Format("Fixed: {0}", state.FixCount);

    this.ElapsedTimeLabel.Text = string.Format("Elapsed Time: {0}", GetProgressElapsedString());

    if (state.Result != null)
    {
        this.dataGridView1.Rows.Add(state.Result);
    }
}

问题...问题是如果文件夹中有 3 个文件(名为 Assembly1、Assembly2 和 Assembly3),网格中的输出显示所有三个文件都被命名为 Assembly3。我解决这个问题的唯一方法是让线程休眠。这不是一个选项,因为我必须 运行 对于一个包含大约 18,000 个文件的文件夹,并且必须休眠一毫秒将花费很长时间。但是,我需要得到有效的结果。请帮助:-)

与其在循环外创建 state 对象并在每次迭代中改变它,不如为每次迭代创建一个新实例。这可以通过简单地将变量的声明移动到循环内来完成。