【问题标题】:Background Worker Completed Event is firing before it is actually finished doing work后台工作人员已完成事件在实际完成工作之前触发
【发布时间】:2015-07-24 21:03:15
【问题描述】:

在我的应用程序中,当用户单击菜单项时,系统会提示他们选择一个文件,然后我使用后台工作程序加载和解析该文件,并在此操作期间向进度条报告进度。工作完成后,我启动一个新窗口,将解析的数据传递给该窗口。出于某种原因,新窗口在解析数据之前打开,并传递空参数而不是数据。

我的点击事件:

private void CIRCUIT_INSTALATION_SCHEDULED_Click(object sender, RoutedEventArgs e)
{
    //prevents users from selecting other menu items 
    disableAll();

    System.Windows.Forms.OpenFileDialog mainExcelFileDialog = new System.Windows.Forms.OpenFileDialog();
    mainExcelFileDialog.InitialDirectory = System.Configuration.ConfigurationManager.AppSettings["MainWorkbookDirectory"];
    mainExcelFileDialog.Title = "Main Excel File";
    mainExcelFileDialog.ShowDialog();
    string mainPath = mainExcelFileDialog.FileName;
    this.Cursor = System.Windows.Input.Cursors.Wait;
    BackgroundWorker cisWorker = new BackgroundWorker();

    cisWorker.DoWork += cisWorker_DoWork;
    cisWorker.ProgressChanged+=cisWorker_ProgressChanged;
    cisWorker.RunWorkerCompleted += cisWorker_RunWorkerCompleted;            
    cisWorker.RunWorkerAsync(mainPath);            
}

我的工作:

void cisWorker_DoWork(object sender, DoWorkEventArgs e)
{            
    BackgroundWorker worker = sender as BackgroundWorker;
    using (FileStream fs = new FileStream(e.Argument.ToString() , FileMode.Open))
    {
        //copy filestream to memorystream chunk by chunk, reporting progress.
        using (MemoryStream ms = new MemoryStream())
        {
            byte[] buffer = new byte[32768];
            int read;
            int steps = Convert.ToInt32(fs.Length / buffer.Length);
            int i = 0;
            while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
            {

                ms.Write(buffer, 0, read);
                i++;
                var progress = new Decimal(i) / new Decimal(steps);
                var outOf = Math.Round(progress * 50);
                worker.ReportProgress(Convert.ToInt32(outOf));
            }

            worker.ReportProgress(50);
            ms.Position = 0;
            //load excel workbook dataset from memorystream
            using (var xlr = Excel.ExcelReaderFactory.CreateOpenXmlReader(ms))
            {
                xlr.IsFirstRowAsColumnNames = true;
                mainWorkbook = xlr.AsDataSet();
                worker.ReportProgress(100);

            }

        }
    }
}

我的完成:

void cisWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    this.Cursor = System.Windows.Input.Cursors.Arrow;
    CircuitInstallationScheduledWindow CIS_Window = new CircuitInstallationScheduledWindow();
    CIS_Window.Show();
    CIS_Window.Closed += CIS_Window_Closed;
}

编辑: 我将 mainPath 参数添加到 cisWorker.runWorkerAsync() 方法中。不幸的是,问题仍然存在。

【问题讨论】:

  • 根据提供的代码,我没有看到您将任何数据传递给 CIS_Window。也许这就是为什么它是空的?如果不是,请说明数据是如何传递的。
  • 您在 DoWork 中遇到异常,而在 Completed 中忽略它。有关规范的 Completed 事件,请参阅 this answer
  • 不,你是对的。上次我必须忘记传递 mainPath 参数时,我一直在更改我的代码以试图修复这个问题。我改变了它,但它仍然开始得太早。我将编辑问题。
  • 如果我在 DoWork 中遇到异常,为什么不抛出异常?我没有任何尝试/捕获。我怎么知道异常是什么以便我可以处理它?
  • 旁注...您应该检查mainExcelFileDialog.ShowDialog(); 的结果是否为OK。如果用户点击取消,您将处理什么文件名?...并且您的 UI 将被禁用,因为您已经调用了 disableAll();!

标签: c# events backgroundworker


【解决方案1】:

基本上你应该检查你的数据不为空,即在 DoWork 期间没有发生错误

void cisWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error == null)
    {
        /* Your mainWorkbook shouldn't be null */

        this.Cursor = System.Windows.Input.Cursors.Arrow;
        CircuitInstallationScheduledWindow CIS_Window = new CircuitInstallationScheduledWindow();
        CIS_Window.Show();
        CIS_Window.Closed += CIS_Window_Closed;
    }
    else
    {
        // Handle error
    }
} 

【讨论】:

    【解决方案2】:

    Henk Holterman 是对的。我收到一个错误,因为我没有设置cisWorker.WorkerReportsProgress = true; 我仍然不知道为什么错误没有破坏调试器,因为它没有被处理,但我在我的 Completed 方法中做了一个打印语句,它帮助我跟踪找出罪魁祸首。

    void cisWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            Console.WriteLine(e.Error);
            this.Cursor = System.Windows.Input.Cursors.Arrow;
            CircuitInstallationScheduledWindow CIS_Window = new CircuitInstallationScheduledWindow(mainWorkbook, abfsDatabase);
            CIS_Window.Show();
            CIS_Window.Closed += CIS_Window_Closed;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-29
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 2022-07-06
      • 2017-10-06
      相关资源
      最近更新 更多