在更新ProgressBar期间,UI卡住了

时间:2012-03-25 16:18:50

标签: c# winforms

我正在使用Pcapdot.net DLL,以便将数据包缓冲区发送到我的网络适配器。我检查了我的Wireshark文件并收集了所有信息,例如包数,持续时间等。 我的主类发送缓冲区并有几个属性(包的数量,持续时间..)在主线程中,我使用BackgroundWorker.ProgressChanged检查此类:

            bgWoSingle = new BackgroundWorker();
            bgWoSingle.WorkerReportsProgress = true;
bgWoSingle.ProgressChanged += new ProgressChangedEventHandler(bgW_ProgressChanged);

Wireshark文件中的每个数据包都有一个timstamp,当然我可以通过增加或减少数据包之间的时间戳来以其他速率发送此缓冲区。 现在我的问题是:

我正在检查的一个属性是我已经发送了多少个数据包。因为我知道我的文件包含多少个数据包,所以我可以通过进度条显示进度。如果我通过删除数据包播放之间的所有延迟将发送速率更改为最大值,则速度非常快,进度条和所有UI都会停止,直到它完成发送所有数据包。我该怎么改变它?也许通过另一个线程更新我的ProgressBar?

这是我检查课程的功能:

  void bgW_ProgressChanged(object sender, ProgressChangedEventArgs e)
  {
    //bla bla bla (check all Class properties)

        pcap = e.UserState as Pcap;
        progressBar1.Value = e.ProgressPercentage; //here is my progressBar update


    //bla bla bla (check all Class properties)
  }

2 个答案:

答案 0 :(得分:6)

您只是经常调用ReportProgress()。通常情况下,UI线程充满了调用请求,并且不再处理其常规职责。喜欢绘画和回应输入事件。因为当它准备好执行下一个通知时,还会有另一个请求调用ProgressChanged事件处理程序,它会先行。

你需要将它降低到合理的速度。合理易于定义,你只为人眼做这件事。当你这样做的速度超过每秒20次时,除了模糊之外什么都看不到。你现在已经过去了,可能超过每秒一千次。一种简单的方法是在调用ReportProgress之前计算50条记录。必要时调整。

答案 1 :(得分:1)

我不知道Pcapdot.net,但我知道Winforms所以我可以给你一些提示。

在窗口没有响应的情况下,您的用户界面似乎卡住了(您无法点击活动按钮或编辑文本框,如果您尝试窗口变为灰色)。在这种情况下,您确实存在线程问题。我不知道BackgroundWorker是一个库类还是你创建的类,但必须确保在另一个线程中完成任何I / O操作。虽然这个名字暗示它发生了,但我不确定你是如何开始这个过程来对抗API的假设。例如,某些库允许您调用分叉另一个线程的start方法,而其他库则要求您从已经分叉的线程调用execute方法。这有所不同。

为了从非UI线程更新UI,您必须始终使用[Control.Invoke][1]方法(如果需要暂停线程直到UI更新)或Control.BeginInvoke(如果要继续) ASAP)。

我的Lambda-fu每天都没有接受过培训,所以如果我的语法错误,请纠正我

progressBar1.Invoke(delegate() {progressBar1.Value = e.ProgressPercentage;});

在第二种情况下,如果进度条无法进展,您的用户界面卡住了,请先确保触发了该事件。其次,最重要的是,无法从非UI线程更新UI。势在必行!

<击>

如果你在try-catch中运行progressChanged方法,我会发现麻烦,因为当你更新progressBar百分比时,你会得到一个可以屏蔽的异常。我也希望ProcessPercentage是介于0和100之间的整数,而不是介于0和1之间的double,这会导致条形图明显无法进展。