Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 后台工作人员报告进度延迟_C#_Winforms_Backgroundworker - Fatal编程技术网

C# 后台工作人员报告进度延迟

C# 后台工作人员报告进度延迟,c#,winforms,backgroundworker,C#,Winforms,Backgroundworker,我对backgroundworker的reportprogress函数有问题。我在worker的doWork函数中使用odbc驱动程序读取数据记录,在读取每一行之后,我调用reportProgress函数将这一行添加到显示中。有时这是可行的,有时报告进度会等待,直到我读取任意数量的记录(例6),然后添加与上次读取的记录相同的6条记录。例如,在下面代码中的打印中,我得到如下结果: ROW: 1: 00000001 ABS 1: 00000001 ROW: 2: 00000002 ROW: 3: 0

我对backgroundworker的reportprogress函数有问题。我在worker的doWork函数中使用odbc驱动程序读取数据记录,在读取每一行之后,我调用reportProgress函数将这一行添加到显示中。有时这是可行的,有时报告进度会等待,直到我读取任意数量的记录(例6),然后添加与上次读取的记录相同的6条记录。例如,在下面代码中的打印中,我得到如下结果:

ROW: 1: 00000001
ABS 1: 00000001
ROW: 2: 00000002
ROW: 3: 00000003
ROW: 4: 00000010
ROW: 5: 00000011
ROW: 6: 00000012
ROW: 7: 00000013
ROW: 8: 00000014
ROW: 9: 00000015
ROW: 10: 00000015
ABS 10: 00000015
ABS 10: 00000015
ABS 10: 00000015
ROW: 11: 00000016
ABS 11: 00000016
ABS 11: 00000016
ABS 11: 00000016
ABS 11: 00000016
ABS 11: 00000016
ABS 11: 00000017
ROW: 12: 00000017
ABS 12: 00000017
ABS 12: 00000017
有人建议在我打电话报告进度后再睡,但我不想这样做

这是我在DoWork中的代码:

while (!terminateRead)
{
    if (reader.Read())
    {
        try
        {
            for (int i = 0; i < columnCount; i++)
            {
                if (reader != null)
                {
                    row[i] = reader.GetString(i);
                }
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("Read Process interrupted");
        }
        currentRow++;
        double perc = ((double)currentRow / rowCount) * 100.0;
        int percentageComplete = Convert.ToInt32(perc);
        Console.WriteLine("ROW: " + currentRow + ": " + row[0]);
        backgroundWorker1.ReportProgress(percentageComplete, row);
    }   
如中所述

对ReportProgress方法的调用是异步的,返回 马上。ProgressChanged事件处理程序在线程上执行 这就产生了后台工作人员

因此,后台工作人员不会等待处理
ProgressChanged
事件,而是继续读取行并引发事件。另一方面,所有处理程序都在主线程上执行,而主线程还有另一个作业要做,所以它们只是被调度的。还要记住,处理此事件可能需要比处理一个步骤更多的时间。这就是为什么处理速度更快的原因

但是为什么要分批处理呢?线程不执行某个方法并退出—它们有一些时间来执行该任务。这就是为什么您会看到在一行中执行多个处理程序的原因——这是给主线程处理的唯一时间窗口。如果有几个处理程序等待执行,它们都开始执行

最后一件事是
currentRow
问题。在处理程序中,您可以看到处理的最后一行的
currentRow
值,因为您在两个线程中使用相同的变量。在将该值传递给处理程序之前,处理程序无法猜测引发事件时哪个值是
currentRow
。如果不想创建用于在线程之间传递这些参数的类,可以使用简单数组或动力学:

 backgroundWorker1.ReportProgress(percentage, new object[]{ currentRow, row });
然后在处理程序中,您可以从引发事件的时间获取
currentRow
值:

 object[] state = (object[])e.UserState;
 string[] row = (string[])state[1];
 int currentRow = (int)state[0];

不要忘记将
currentRow
设置为
DoWork
处理程序的本地变量-它不应该是表单中的全局变量。

不要使用
Console.WriteLine()
DoWork()
方法中,它应该是
RunWorkerCompleted
事件处理程序或
ReportProgress
方法的一部分。
DoWork
方法的任务应该是处理长时间运行的工作或报告进度,并且它应该与GUI线程交互(就像它不应该调用控制台方法一样)

请将此行移出
DoWork()
方法,并调用
backgroundWorker1\u ProgressChanged
RunWorkerCompleted
事件处理程序(如果尚未添加,则需要添加事件处理程序):

有关BackgroundWorker组件的更多信息,请参阅:


您使用的是哪个版本的.Net?我会拿出
控制台.WriteLine
行-您的UI线程和您的后台工作人员将相互竞争以获得对它的独占访问权。我不确定这是问题所在。因为显示的数据看起来不正确,所以我才打印出来。删除打印仍然会导致数据网格视图中出现重复。我对这一信息投了赞成票。我通过线程化和强制do work函数等待报告进度来解决这个问题complete@O.Fouda,BackgroundWorker的
DoWork
方法已经生成了一个线程,您不应该使用其他线程。只要参考链接并理解概念,你就应该能够通过BackgroundWorker实现你想要的。
 object[] state = (object[])e.UserState;
 string[] row = (string[])state[1];
 int currentRow = (int)state[0];
Console.WriteLine("ROW: " + currentRow + ": " + row[0]);