BackgroundWorker 仅在调试模式下报告进度

BackgroundWorker only reporting progress in debug mode

我有一个程序可以读取一些数据,然后根据这个创建一个大数据table,最后将这个数据table导出到一个.csv文件。由于 table 的生成需要相当长的时间,我创建了一个后台工作程序,它应该显示在我的主窗体上的列表框中,其中程序正在运行。

下面是我的代码摘要:

    private readonly BackgroundWorker worker = new BackgroundWorker();

    public void get_data()
    {
        worker.DoWork += worker_DoWork;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        worker.ProgressChanged += worker_ProgressChanged;
        worker.WorkerReportsProgress = true;
        worker.RunWorkerAsync();

    }

    private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        worker.ReportProgress(1, "Starting");

        mydata = read_file();

        worker.ReportProgress(1, "Step 1 done!");

        fullmodel = combine_data(mydata);

        worker.ReportProgress(1, "Step 2 done!");

        DataTableToCSV(fullmodel, ';');

    }

    private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {

        MainWindow.listBox.Items.Add(e.UserState);      

    }

    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    { 

    }

当我 运行 我的程序处于 VS2015 的调试模式时,这工作正常,"Starting"、"Step 1 done!" 和 "Step 2 done!" 应该出现在列表框中。但是,当我 运行 Visual Studio 之外的应用程序时,ProgressChanged 事件似乎只被触发一次 - "Starting" 按预期显示在列表框中,但仅当后台工作者完成时,另一个在 运行ning 时应报告的两个条目立即显示在列表框中,并且 UI 在程序 运行ning 时冻结。

我无法使用空 read_file()combine_data()DataTableToCSV() 方法重现您的场景,因此我认为这可能是此方法的问题。例如,read_file() 可能会抛出异常,因为无法在磁盘上找到文件或类似的东西。

抛出后台异常的特点是不会停止主应用

通过MSDN

If the operation raises an exception that your code does not handle, the BackgroundWorker catches the exception and passes it into the RunWorkerCompleted event handler, where it is exposed as the Error property of System.ComponentModel..::.RunWorkerCompletedEventArgs. If you are running under the Visual Studio debugger, the debugger will break at the point in the DoWork event handler where the unhandled exception was raised.

因此,您可以将代码添加到 worker_RunWorkerCompleted() 方法并检查 Exception 是否被抛出。

Hans Passant 上面的评论是正确的提示。在我调用的方法中,在某些循环中实现了相当多的 .ReportProgress,似乎 UI 线程跟不上这个(虽然没有触发异常)。当 运行 程序处于调试模式时,由于某种原因,程序 运行 慢了很多,然后 UI 线程似乎没有这个问题。