减少/删除进度条内文本的闪烁

时间:2013-04-08 09:48:01

标签: c# winforms progress-bar backgroundworker

我正在使用backgroundWorker1执行DLL,它通过引用更新变量i。要使用i更新进度条,请使用以下代码。我还想将百分比显示为文本。问题是文本(不是进度条)闪烁了很多。如何减少/消除此闪烁?增加睡眠持续时间不是一种选择。

BackgroundWorker backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.DoWork += (s, args) =>
{
   Mydll.MyCFunction(ref i);
};
backgroundWorker1.RunWorkerAsync();

while (backgroundWorker1.IsBusy)
{
    backgroundWorker1.ReportProgress(i * 100);               
    backgroundWorker1.ProgressChanged += (s, e) =>
    {
       progressBar1.Refresh();
       progressBar1.Value = e.ProgressPercentage;
       progressBar1.CreateGraphics().DrawString(e.ProgressPercentage.ToString() + "%",
            SystemFonts.DefaultFont, Brushes.Black,
            new PointF(progressBar1.Width / 2 - 10, progressBar1.Height / 2 - 7));
    };
    Application.DoEvents();
    System.Threading.Thread.Sleep(200);
}

感谢。

4 个答案:

答案 0 :(得分:1)

您的代码将多次订阅ProgressChanged事件。您只需要订阅一个事件即可。拥有所有这些事件意味着每次进度都会发生变化,进度条上会有越来越多的刷新。

我建议为进度更改事件创建一个单独的事件处理程序,并确保只订阅一次。

所以,试着保持你的设计:

将事件处理程序订阅到ProgressChanged(事件处理程序在其他地方声明)

循环 {

ReportProgress

的DoEvents

睡眠 }

作为旁注,你为什么要睡觉呢?

答案 1 :(得分:1)

如果图形闪烁,则应启用双缓冲。

DoubleBuffered = true

SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

有关详细信息:http://msdn.microsoft.com/en-us/library/3t7htc9c.aspx

答案 2 :(得分:0)

您的代码有多个错误。其中一个,一般来说是调用Application.DoEvents。这在15年前的VB6中可能有用,但那是技术石器时代。您还将多个相同的处理程序附加到事件,这意味着在100次循环后,您的绘图将按百分比调用100次。

如果有这么多错误,很难提出一个简单的修复方法。看看here有两个简单的方法来完成这项工作。试着了解发生的事情,顺序和原因。

答案 3 :(得分:0)

首先,我会删除行Application.DoEvents();(关于do事件的优秀post),这通常表示糟糕的多线程设计。我也会亲自删除Thread.Sleep电话。

其次,您应该订阅工作循环的ProgressChanged OUTSIDE。例如:

public Form1()
{
    bgWorker.ProgressChanged += bgWorker_ProgressChanged;
}

private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar.Value = e.ProgressPercentage;
    progressBar1.CreateGraphics().DrawString(e.ProgressPercentage.ToString() + "%",
            SystemFonts.DefaultFont, Brushes.Black,
            new PointF(progressBar1.Width / 2 - 10, progressBar1.Height / 2 - 7));
}