【问题标题】:C# Progress Bar not cooperatingC# 进度条不合作
【发布时间】:2011-03-12 01:47:46
【问题描述】:

我遇到了一个非常奇怪的情况。这应该很简单,但我不确定为什么会这样。

我有一个选框进度条设置为 visible=false,因为它是初始状态。然后在运行时的某一时刻,我调用了我的一个函数,在调用它之前,我将 PB 设置为可见 = true,在函数结束后,我将其设置回可见 = false。没有比这更简单的了。

If (something)
{
  pb.visible=true;
  runMyfunction(x, x, x, x,);
  pb.visible=false;
}

问题是我从未见过 PB。如果我注释掉我的函数并删除 =false,PB 就会出现,但是一旦我把函数放回那里,PB 就永远不会出现。

我尝试了各种方法。使用 If 语句确保在它触及函数之前我得到一个进度条,并且它仍然保持 PB 隐藏。

我错过了什么吗?这似乎不应该那么复杂。显示对象、运行函数、隐藏对象。正确的? :)

【问题讨论】:

  • 这是 winforms 还是 asp.net 还是 WPF 还是什么?
  • 你指的是ASP.NET的WinForms进度条吗?

标签: c# progress-bar


【解决方案1】:

我的猜测是 myRunFunction() 在 UI 线程上运行。

尝试在BackgroundWorker 中运行它并在调用RunWorkerAsync 之前启动ProgressBar 并在RunWorkerCompleted 事件中停止它。

用代码示例编辑:

public class SomeClass
{
    private BackgroundWorker _myFunctionBackgroundWorker;
    private SomeProgressBar pb;

    public SomeClass()
    {
        _myFunctionBackgroundWorker = new BackgroundWorker();
        _myFunctionBackgroundWorker.DoWork += myFunctionBackgroundWorker_DoWork;
        _myFunctionBackgroundWorker.RunWorkerCompleted += myFunctionBackgroundWorker_RunWorkerCompleted;

        pb.visible = true;
        _myFunctionBackgroundWorker.RunWorkerAsync();
    }

    private void myFunctionBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        runMyfunction();
    }


    private void myFunctionBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        pb.visible = false;
    }
}

【讨论】:

  • 工作就像一个魅力!谢谢你。不过有一个问题。我的函数有一些 catch 语句,当它遇到这些语句时,我得到一个跨线程错误。我猜出于某种原因,那些没有被封装在后台工作人员启动的原始线程中。无论如何,我可以解决这个问题?
  • 没关系,我明白了。不得不重新安排我的功能,但是一旦我将所有结果都传递给 e.Result,一切都运行良好!再次感谢您让我使用 backgroundworker 以正确的方法进行设置。
【解决方案2】:

这是因为您的函数占用了 UI 线程。将 ProgressBar 设置为可见需要释放 UI 线程来绘制它,但您会继续处理您的函数,而该函数永远不会给它绘制时间。

您可以通过调用来解决这个问题:Application.DoEvents 它会停止处理您的方法足够长的时间来处理一些 Windows 消息(并进行相关绘图)。

Application.DoEvents 的最大问题是,假设您从runMyfunction() 更新进度条,您将不得不不断调用Application.DoEvents 以允许您的 PB 绘制,否则您会看到它,但您永远不会看到它更新。

更好的解决方案是将您的runMyfunction() 调用推送到后台线程并从那里异步更新进度条。这当然要复杂得多,但会带来更好的用户体验。

【讨论】:

  • BackgroundWorker 可能是这种情况的理想选择。它封装了很多你需要的方法。
  • 这很好,因为它确实解决了问题。但是,由于我的应用程序在函数运行约 10 秒时仍处于捆绑状态,因此选取框永远不会移动。我只是在函数运行时显示选框的简单路由,然后在最后将其删除。我将使用 backgroundworker 尝试 ROBOlav 的建议。
【解决方案3】:

在您的 runMyFunction() 方法调用内部 Application.DoEvents() 强制您的应用重绘并处理 Windows 消息循环:

例如

void myRunFunction()
{
  while (someFlag)
  {
   // do work
   pb.Value = someValue;
   Application.DoEvents();
  }
}

【讨论】:

    【解决方案4】:

    可能是您的函数正在运行和完成太快,以至于您看不到该栏。我知道我以前也遇到过几次这种情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-29
      • 1970-01-01
      • 2013-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多