C# 为什么异步进度条上的文本会闪烁?

C# 为什么异步进度条上的文本会闪烁?,c#,visual-studio-2012,asynchronous,progress-bar,C#,Visual Studio 2012,Asynchronous,Progress Bar,我想在ProgressBar上显示文本(而不必使用a)。这并不难做到,也不涉及OnPaint方法——如下面代码的按钮1所示。但是,此方法会阻止UI线程,而UI线程是。 不幸的是,我对异步方法的最佳尝试会导致文本闪烁,这非常烦人 有人能告诉我如何在不闪烁的情况下异步更新文本吗 (要运行以下代码,只需将其粘贴到新项目中即可 包含具有3个按钮和3个进度条的窗体) 使用系统; 使用系统图; 使用System.Windows.Forms; 使用System.Threading.Tasks; 使用系统线程;

我想在
ProgressBar
上显示文本(而不必使用a)。这并不难做到,也不涉及
OnPaint
方法——如下面代码的按钮1所示。但是,此方法会阻止UI线程,而UI线程是。 不幸的是,我对异步方法的最佳尝试会导致文本闪烁,这非常烦人

有人能告诉我如何在不闪烁的情况下异步更新文本吗

(要运行以下代码,只需将其粘贴到新项目中即可 包含具有3个按钮和3个进度条的窗体)

使用系统;
使用系统图;
使用System.Windows.Forms;
使用System.Threading.Tasks;
使用系统线程;
namespace progbertest//相应地更改Program.cs中的名称空间
{
公共部分类Form1:Form
{
公共表格1()
{
初始化组件();
}
私有无效按钮1\u单击(对象发送者,事件参数e)
{
//此方法将阻止主UI线程
//(因此冻结了其他按钮)
启动日期(本协议第1条);
}
私有无效按钮2\u单击(对象发送者,事件参数e)
{
//这个方法(和下一个)不阻塞UI,可以同时使用,
//但是文本在闪烁
Task t=新任务(()=>StartUpdate(this.progressBar2));
t、 Start();
}
私有无效按钮3\u单击(对象发送者,事件参数e)
{
Task t=新任务(()=>StartUpdate(this.progressBar3));
t、 Start();
}
私有无效启动日期(ProgressBar progBar)
{

对于(int i=1;i可能是因为您正在从另一个线程绘制字符串。如果您可以使用基于
控件的文本元素,则可以使用BeginInvoke,方式与ProgressBar相同:

// Label progressLbl

private void UpdateProgressFromAnotherThread(int completed, int total, string progressText)
{
    this.progBar.BeginInvoke(new Action(() =>
    {
        this.progBar.Maximum = total;
        this.progBar.Value = completed;
    }));

    this.progressLbl.BeginInvoke(new Action(() =>
    {
        this.progressLbl.Text = progressText;
    }));
}

老实说,定制进度条是你最好的选择。如果你设置正确的话。我知道我没有回答你的问题,所以请不要投反对票,只是提供一个不同的解决方案。我还没有测试过这一点,但理论上它会在每次进度条重新绘制时得出百分比,每次值为他变了

您当前的问题是,每当您更改值时,该条都会重新绘制自身,因此文本会闪烁。如果它没有重新绘制,您将看到绘制的百分比开始相互重叠,这也不好

从设计角度来看,最好将所有内容封装在一个控件中

class CustomProgressBar : ProgressBar {
    public CustomProgressBar() : base() {}

    protected override void OnPaint(PaintEventArgs e) {
        // Call the OnPaint method of the base class.
        base.OnPaint(e);
        string percentStr = this.Value.ToString() + "%";
        PointF location = new PointF(this.Width / 2 - 10, this.Height / 2 - 7);
        // Call methods of the System.Drawing.Graphics object.
        e.Graphics.DrawString(percentStr, new Font("Arial",10), Brushes.Red, location );
    } 
}

谢谢。这是我的第一个策略,但我希望文本放在ProgressBar的顶部,但我找不到任何可以为ProgressLBL提供透明背景的方法。好的,那么也许你可以根据这个问题的答案尝试一些东西(如果你仍然不想创建自定义ProgressBar):谢谢,你可能是对的。但奇怪的是,我的方法在UI线程中运行良好,只在后台线程中闪烁。但我确实喜欢你的自定义progressbar简化版本(比我上面引用的公认答案中的版本简单得多)。我必须试一试
class CustomProgressBar : ProgressBar {
    public CustomProgressBar() : base() {}

    protected override void OnPaint(PaintEventArgs e) {
        // Call the OnPaint method of the base class.
        base.OnPaint(e);
        string percentStr = this.Value.ToString() + "%";
        PointF location = new PointF(this.Width / 2 - 10, this.Height / 2 - 7);
        // Call methods of the System.Drawing.Graphics object.
        e.Graphics.DrawString(percentStr, new Font("Arial",10), Brushes.Red, location );
    } 
}