需要有关线程-C#Windows窗体的帮助

时间:2010-10-21 14:32:46

标签: c# winforms multithreading

我正在尝试创建一个包含表单进度条的线程(只是一个GIF图像)。 我在一个大方法之前就调用了StartProgress()。基本上当线程启动时,它会加载ProgressBar表单(我想一直显示它,只是在不需要时隐藏它)并且ProgressActive设置为true,它应该显示表单直到{{1如果为false,则应隐藏表单(直到进度再次激活)。这是我到目前为止所做的,但它冻结了我:(

ProgressActive

编辑:我正在尝试在静态类中执行此操作。

4 个答案:

答案 0 :(得分:4)

如果使用.NET 2.0或更高版本,是否有任何理由不使用BackgroundWorker?

我之所以这么说是因为BackgroundWorker是基于事件的,所以它暴露了一个像ProgressChanged这样的事件,可以减少代码的整体大小。

答案 1 :(得分:1)

冻结是因为您试图从工作线程更改UI线程中包含的进度条。我建议将工作进程函数中的事件提升到UI线程上的处理程序。您将需要对线程上的处理程序进行调整,如下所示。

private object _lock = new object(); //should have class scope

private void ShowProgressControl(EventArgs e)
{
  if (this.InvokeRequired)
  {
    lock (_lock)
    {
      EventHandler d = new EventHandler(ShowProgressControl);
      this.Invoke(d, new object[] { e });
      return;
    }
  }
  else
  {
    //Show your progress bar.
  }
}

享受!

答案 2 :(得分:1)

问题是您需要一个消息循环才能使任何UI元素正常工作。由于您是在工作线程中创建表单,因此没有消息循环在运行。要创建消息循环,您必须调用Application.RunForm.ShowDialog这两个阻止呼叫。显然,该解决方案会挂断您的工作线程。

最好的办法是创建一个专门用于运行消息循环的独立线程,它可以安全地处理表单和控件。让工作线程定期将进度信息发布到可以在工作线程和UI线程之间共享的变量。然后让UI线程定期轮询(使用System.Windows.Form.Timer)共享变量并相应地更新UI。

作为旁注,我会避免使用Control.InvokeControl.BeginInvoke将进度信息推送到UI线程。您的情况似乎值得采用轮询方式。倾向于推动民意调查的原因是:

  • 它打破了Control.Invoke强加的UI和工作线程之间的紧密耦合。
  • 它将更新UI线程的责任放在它应该属于的UI线程上。
  • UI线程决定更新的发生时间和频率。
  • UI消息泵没有溢出的风险,就像工作线程启动的编组技术一样。
  • 在继续执行下一步之前,工作线程不必等待确认已执行更新(即,您在UI和工作线程上获得更多吞吐量)。

答案 3 :(得分:0)

您应该在主线程上创建进度条。

确保您的繁重程序从另一个线程运行。