线程方法Outrunning ProgressChanged

时间:2015-02-02 21:10:42

标签: c# multithreading backgroundworker

我有一个简单的应用程序,它通过BackgroundWorker在一个单独的线程中执行一个函数,并遇到问题。我正在收集一个字符串数组值并通过ReportProgress方法将其传递回我的ProgressChanged事件,并且我遇到了线程继续并且速度很快的问题,它会超出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中,它会加载我的工作所在的类......

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类... ReportProgress卡在try / catch的中间,因为我无法弄清楚导致问题的原因。所以,我在try中移动了它,甚至不得不添加一个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个文件的文件夹运行此文件,并且必须睡眠一毫秒才能永远。但是,我需要获得有效的结果。请帮助: - )

1 个答案:

答案 0 :(得分:0)

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