【问题标题】:UI stuck during update of ProgressBar在 ProgressBar 更新期间 UI 卡住
【发布时间】:2013-03-24 06:48:55
【问题描述】:

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

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

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

我正在检查的属性之一是我已经发送了多少数据包。因为我知道我的文件包含多少数据包,所以我可以通过进度条显示进度。如果我通过删除数据包播放之间的所有延迟来将发送速率更改为最大值,那么速度是如此之快,进度条和所有 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)
  }

【问题讨论】:

  • “卡住”是指无响应(即窗口在点击时变为灰色,因此您必须从另一个线程执行 I/O)还是只是进度条没有更新?
  • 是的,在点击完成之前它会变成灰色并显示“未响应”消息,我如何通过另一个线程更新我的所有 bgW_ProgressChanged ?

标签: c# winforms


【解决方案1】:

您只是过于频繁地调用 ReportProgress()。 UI 线程经常被调用请求淹没,并且不再处理其常规职责。就像绘画和响应输入事件一样。因为当它准备好执行下一个通知时,还会有另一个调用 ProgressChanged 事件处理程序的请求,它会先执行。

您需要将其放慢到合理的速度。合理很容易定义,你这样做只是为了人眼​​。当您以每秒 20 次以上的速度执行此操作时,除了模糊之外什么都看不到。你现在已经超越了这一点,可能每秒超过一千次。一种简单的方法是在调用 ReportProgress 之前只计算 50 条记录。根据需要进行调整。

【讨论】:

    【解决方案2】:

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

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

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

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

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

    在第二种情况下,您的用户界面卡住,即进度条无法前进,首先确保触发事件。其次,也是最重要的一点,您不能从非 UI 线程更新 UI。势在必行!

    如果您在 try-catch 中运行 progressChanged 方法,我会看到麻烦,因为当您更新 progressBar 百分比时,您会得到一个可能被屏蔽的异常。我还希望 ProcessPercentage 是 0 到 100 之间的整数,而不是 0 到 1 之间的 double,这会导致条形图没有明显进展。

    【讨论】:

    • 我刚看了你的评论,请忽略我问题的第二部分
    • 很抱歉,但我不明白我应该做什么,更新我的 UI 的最佳方法是什么?
    • 使用 lambda 调用 Invoke 方法。几秒钟内的示例
    • this.Invoke((MethodInvoker)delegate { }); ?
    • 好吧,我的代码并不是“lambda 表达式”的最佳示例。最好用它的真名来称呼它:anonymous delegate
    猜你喜欢
    • 2012-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-26
    • 1970-01-01
    • 2023-01-11
    相关资源
    最近更新 更多