C# - 带滚动条样式的ProgressBar

问题描述:

我想在带有滚动样式的窗体上添加一个ProgressBar,以显示用户正在进行的操作。在耗时的操作过程中,表单不会更新,因此ProgressBar也会“冻结”。C# - 带滚动条样式的ProgressBar

我已经检查了几篇关于BackgroundWorker的帖子,但在我的案例中操作不报告进度,这就是为什么我需要一个Marquee栏。

赞赏任何帮助或代码片段。

注:我需要使用.NET 4.0(对XP的支持),所以我不能使用Task.Run :(

button1_Click(object sender, EventArgs e) 
{ 
    progressBar1.Style = ProgressBarStyle.Marquee; 
    progressBar1.MarqueeAnimationSpeed = 50; 

    // INSERT TIME CONSUMING OPERATIONS HERE 
    // THAT DON'T REPORT PROGRESS 
    Thread.Sleep(10000); 

    progressBar1.MarqueeAnimationSpeed = 0; 
    progressBar1.Style = ProgressBarStyle.Blocks; 
    progressBar1.Value = progressBar1.Minimum; 

} 
+0

你知道迭代器的数量在您的消费过程的开始做些什么呢?在这种情况下,我可能会提出一些实施建议。 – Graffito

+0

这不是一个迭代,更像是等待MySQL连接或LDAP响应。 – dobragab

我查了一下BackgroundWorker的几个职位,但在我的情况下, 操作不报告进度,这就是为什么我需要一个跑马灯吧。

您可以使用BackgroundWorker,只是不要使用它的“进度”部分。这两件事并不相互排斥......

例子:

private void button1_Click(object sender, EventArgs e) 
    { 
     button1.Enabled = false; 
     progressBar1.Style = ProgressBarStyle.Marquee; 
     progressBar1.MarqueeAnimationSpeed = 50; 

     BackgroundWorker bw = new BackgroundWorker(); 
     bw.DoWork += bw_DoWork; 
     bw.RunWorkerCompleted += bw_RunWorkerCompleted; 
     bw.RunWorkerAsync(); 
    } 

    void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     // INSERT TIME CONSUMING OPERATIONS HERE 
     // THAT DON'T REPORT PROGRESS 
     Thread.Sleep(10000); 
    } 

    void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     progressBar1.MarqueeAnimationSpeed = 0; 
     progressBar1.Style = ProgressBarStyle.Blocks; 
     progressBar1.Value = progressBar1.Minimum; 

     button1.Enabled = true; 
     MessageBox.Show("Done!"); 
    } 
+0

听起来不错!是否有可能从bw_RunWorkerCompleted访问所有表单控件? (所以它在同一个线程上运行?) button1.Enabled = true; MessageBox.Show(“Done!”); 这表明了这一点。 – dobragab

+0

是的,你可以安全**从RunWorkerCompleted()事件中访问所有的控件,因为它已经被BackgroundWorker控件编组到主UI线程。如果将来使用'ProgressChanged()'事件也是如此。 –

你仍然需要在不同的线程运行耗时的工作。 ..你是在UI线程,这意味着UI没有机会做任何UI更新上运行它(因此冻结您见证)!

您应该考虑使用Task<>代替BackgroundWorker

见mor。的https://msdn.microsoft.com/en-us/library/hh195051%28v=vs.110%29.aspx电子信息Task<>


如果您不能使用Task<>,那么你应该恢复到BackgroundWorker并使用WorkCompleted情况下,停止选取框并移动程序到其下一步的操作。

+0

谢谢,我会看看它。请注意,我无法使用Task.Run,​​正如我在编辑中提到的那样。是否有任何由.NET 4.0支持的替代方法? – dobragab

已解决。不过,我认为这是处理它的最不优雅的方式。

button1_Click(object sender, EventArgs e) 
{ 
    progressBar1.Style = ProgressBarStyle.Marquee; 
    progressBar1.MarqueeAnimationSpeed = 50; 


    Task task = Task.Factory.StartNew(() => 
    { 
     // INSERT TIME CONSUMING OPERATIONS HERE 
     // THAT DON'T REPORT PROGRESS 
     Thread.Sleep(10000); 
    }); 

    while (!task.IsCompleted) 
    { 
     Application.DoEvents(); 
     Thread.Sleep(1); 
    } 

    progressBar1.MarqueeAnimationSpeed = 0; 
    progressBar1.Style = ProgressBarStyle.Blocks; 
    progressBar1.Value = progressBar1.Minimum; 

} 
+0

这通常是一个**非常糟糕的主意,让你的点击处理程序像这样的轮询循环。 –