【问题标题】:Progress bar form not fully loading进度条表单未完全加载
【发布时间】:2012-11-08 17:01:50
【问题描述】:

我正在编写一个加载时间较长的程序(5-30 秒)。我想要一个以选取框样式进度条开头的表单,以便用户知道正在做某事。

public FrmMain()
{
     var loading = new FrmLoading();
     loading.Show();

     InitializeComponent();

     // other start up code here

     loading.Close()
}

现在,loading 弹出来就好了。问题是标签和进度条什么都没有显示,看起来就像是崩溃了。我已经查看了BackgroundWorker,但老实说,我并不完全理解如何让它为我工作。我尝试按照以下教程和示例进行操作:

但我的脑袋就是不明白。有没有其他方法可以让表单正确加载?感谢您的所有帮助。

编辑

我的BackgroundWorker 尝试包括我创建一个函数来执行我在FrmMain 中完成的所有操作。所以,我有:

public FrmMain()
{
    Loading = new FrmLoading();
    Loading.Show();

    backgroundWorker1.RunWorkerAsync();
}

private void FormLoading()
{
     // Initialize and loading elements of the form
     InitializeComponent();
}
private void BackgroundWorker1DoWork(object sender, DoWorkEventArgs e)
{
    FormLoading();
}

private void BackgroundWorker1RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    Loading.Close();
}

但我在backgroundWorker1.RunWorkerAsync(); 上不断收到NullReferenceException

【问题讨论】:

  • 这正是使用后台工作人员的情况。请说明您使用它的尝试,并说明您在使用该解决方案时遇到的问题。一般的方法很简单。构造函数显示加载表单,启动后台工作者,DoWork 事件执行长时间运行的任务,完成事件关闭加载表单。技术上还有其他方法,例如使用任务、异步/等待、直接线程访问等,但如果您在使用 BGW 时遇到问题,使用这些方法会更难,而不是更容易。
  • 问题是您正在主 (UI) 线程中进行所有处理。当你这样做时,线程没有机会绘制控件,并且 Windows 认为你的应用程序被卡住了。正如@Servy 刚刚写的那样,您应该在后台线程中进行处理(BackgroundWorker 适合这种情况),然后在完成后返回主线程。
  • 编辑显示BackgroundWorker的尝试。
  • FrmMain() 构造函数丢失了 InitializeComponent() 调用。是的,那会爆炸。

标签: c# winforms progress-bar


【解决方案1】:

一个鲜为人知或经常被遗忘的框架库是 Microsoft.VisualBasic。您可以将它与 C# 应用程序一起使用。只需添加一个 Reference ... 和这个类。它处理所有后台工作线程和其余部分。

public class MyApplication : WindowsFormsApplicationBase
{
    private static MyApplication _application;

    public static void Run(Form form)
    {
        _application = new MyApplication{ MainForm = form };
        _application.Run(Environment.GetCommandLineArgs());
    }

    protected override void OnCreateSplashScreen()
    {
        this.SplashScreen = new MySplashScreenForm();
    }
}

最后,将 Program.Main() 下的应用启动更改为:

Application.Run(new Form1());

   MyApplication.Run(new Form1());

如果你不熟悉,这个类还提供了更多的特性,比如单实例处理,绝对值得一看。

【讨论】:

  • 你能详细说明一下吗?我试图合并一个进度条只是为了显示几秒钟。问题是在表单加载时(说加载报告。),它没有关闭。它保持这种状态。这个带有进度条的表单不需要在应用程序启动时加载,而是在用户单击特定报告时加载。报告需要运行,并且在数据库执行过程中,需要显示进度条。谢谢!
  • @Veena 这个答案是特定于应用程序加载的。 Google 'C# Progress Dialog' 以获得一些满足您需求的有用信息,例如:csharpmentor.blogspot.com/2009/05/…
【解决方案2】:

也许这会有所帮助:

添加一个:

Shown += new EventHandler(Form1_Shown);

在你的InitializeComponent();之后。

并添加:

void Form1_Shown(object sender, EventArgs e)
{
    Refresh();
}

另外,如果您没有订阅设计器中的 BackgroundWorker1DoWork 事件处理程序,您必须添加:

backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);

【讨论】:

    【解决方案3】:

    我最终做的可能并不优雅,但它完成了我所需要的。

    public FrmMain()
    {    
         InitializeComponent();
    
         backgroundWorker1.RunWorkerAsync();
    
         var loading = new FrmLoading();
         loading.ShowDialog();
    }
    
    private void BackgroundWorker1DoWork(object sender, DoWorkEventArgs e)
    {
        DbQuery();
    }
    
    private void BackgroundWorker1RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Loading.Close();
    }
    

    这会调出我的loading 表单,使其具有焦点并完全加载。由于我在调用ShowDialog() 之前调用了DoWork,因此BackgroundWorker 继续工作。一旦DbQuery() 完成,它就会调用BackgroundWorker1RunWorkerCompleted(),这会关闭我的FrmLoading 并继续我的程序。感谢所有发帖的人。

    【讨论】:

      猜你喜欢
      • 2012-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多