Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#Winforms-ProgressBar无法正确显示和重置_C#_.net_Visual Studio_Winforms - Fatal编程技术网

C#Winforms-ProgressBar无法正确显示和重置

C#Winforms-ProgressBar无法正确显示和重置,c#,.net,visual-studio,winforms,C#,.net,Visual Studio,Winforms,我有一个windows桌面应用程序,我正在用visual basic中的windows窗体编写它。在这个应用程序中,我想显示一个简单的进度条,但我遇到了一个奇怪的问题。下面是更新进度条的简单for循环示例: pBar.Visible = true; // pBar.Minimum and pBar.Step are both set to 1 using the properties pane in the design page pBar.Maximum = 100; for (int j =

我有一个windows桌面应用程序,我正在用visual basic中的windows窗体编写它。在这个应用程序中,我想显示一个简单的进度条,但我遇到了一个奇怪的问题。下面是更新进度条的简单for循环示例:

pBar.Visible = true;
// pBar.Minimum and pBar.Step are both set to 1 using the properties pane in the design page
pBar.Maximum = 100;
for (int j = 0; j < 100; j++) {
    double pow = Math.Pow(j, j); //Calculation
    pBar.PerformStep();
}
pBar.Visible=true;
//使用设计页面中的属性窗格将pBar.Minimum和pBar.Step都设置为1
pBar.最大值=100;
对于(int j=0;j<100;j++){
双功率=数学功率(j,j);//计算
pBar.PerformStep();
}
上面的工作很好,但是,我希望能够重置进度条,以便稍后再次使用它。我假设我可以简单地在for循环之后设置
pBar.Value=1
,但奇怪的是,这打破了进度条。该条不会像以前那样稳步增加,而是根本不会填充。如果我设置了
pBar.Value=50
,则该条从中点开始,不会移动。它的行为类似于在for循环之前执行
pBar.Value
,或者在每次循环迭代期间设置
pBar.Value
(我已经确保没有将
pBar.Value
语句错误地放在for循环中)

我认为发生这种情况的唯一原因是,C#异步运行我的for循环,并且立即设置值,然后由于某种原因它没有得到更新。我试着四处寻找答案,但到目前为止,我所找到的都是创建后台工作人员的方法(我对此不感兴趣),我重置进度条的方法应该是有效的


为什么会发生这种情况?

使用计时器踏板来监视ProgressBar值是否达到最大值(100),然后在为真时将其重置为0。您还需要使用此小技巧绕过Win7\10。我只是做了一个简单的解释,可以帮助你更好地理解解决方案

以下是基于原始代码的完整代码

        private void button1_Click(object sender, EventArgs e)
    {
        timer1.Enabled=true;

        pBar.Visible = true;
        pBar.Step = 1;
        pBar.Minimum = 0;

        pBar.Maximum = 100;
        for (int j = 1; j < 101; j++)
        {
            // double pow = Math.Pow(j, j); //Calculation
            pBar.Value = j;
            pBar.Value = j-1;
            pBar.PerformStep();
            Thread.Sleep(20);
        }



    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        if (pBar.Value == 100)
        {
            pBar.Value = 0;
            timer1.Enabled = false; // stop timer process
        }
    }
private void按钮1\u单击(对象发送者,事件参数e)
{
timer1.Enabled=true;
pBar.Visible=true;
pBar.Step=1;
pBar.最小值=0;
pBar.最大值=100;
对于(int j=1;j<101;j++)
{
//双功率=数学功率(j,j);//计算
pBar.值=j;
pBar.值=j-1;
pBar.PerformStep();
睡眠(20);
}
}
私有无效计时器1_刻度(对象发送方,事件参数e)
{
如果(pBar.Value==100)
{
pBar.值=0;
timer1.Enabled=false;//停止计时器进程
}
}

好的,下面是我试图回答你的问题:

我不认为在循环后将进度条的值重置为1时进度条不会“更新”。我认为整个进度条的动画都是假的

我查看了
ProgressBar
的源代码。我们注意到,
ProgressBar.Value
ProgressBar.PerformStep
最终都会调用它,从而向底层本机控件发送消息。然后MSDN告诉我们,该条应该在每次收到此消息时重新绘制

然而,我怀疑这个控件在某种程度上虚拟了这个条的“真实”动画。我的猜测是,
PBM_SETPOS
消息会立即被考虑到位置值(我们不希望我们的条每次都不知道它的值),但它们也必须被发送到某个队列以进行动画

动画可能会花费相当长的时间,如果发生需要停止或修改动画的事情,例如向后移动,动画将被取消。。。 假设您交替使用值1和51,而不是增加当前值,您希望看到哪种类型的动画

我通过替换
pBar.PerformStep()模拟了这一点在您的代码中:

pBar.Value=j%2*50+1;
当然,没有尾随的
pBar.Value=1

生成的动画不是令人恶心的1到51之间的往返,而是从1到51之间的干净平滑的过渡:)

我认为这证明了我的观点,即动画正在自己选择它想要的值,因此当快速在100之后设置1时,动画引擎决定不渲染任何内容

因此,如果要避免这种影响,最简单的方法是在使用进度条之前将其值重置为1,而不是在使用之后(顺便说一句,使用进度条时不假定进度条值为1,这可能是更好的编程实践)


PS:作为最后一点,同样的现象被用作在动画完成之前在进度条上强制一个高值的技巧

在您的情况下,您可以:

private void goslowyto100()=>pBar.Value=100;
私有的void GoQuicklyTo100()
{
pBar.最大值=101;
pBar.值=101;
pBar.最大值=100;
pBar.值=100;
}
希望这能回答你的问题

for循环后的pBar.Value=1会导致进度条不更新

可能控件未失效/更新导致绘制事件发生,请使用以下代码测试理论:

尝试:

C#

最好使用第二个线程来实现更平滑的显示,尽管单线程进度条是完全有效的

放入
pBar.Invalidate()在循环的最后应该回答您的问题,我想用一个您可能会涉及到的示例来说明为什么会发生这种情况


还请注意,有些人更喜欢使用
更新

使控件在其客户端区域内重新绘制无效区域

而不是
使无效

使控件的整个表面无效,并使控件重新绘制

我在本例中使用后者对th的整个表面进行故障排除
for (int j = 0; j < 100; j++) {
...
}

pBar.Value = 1
pBar.Invalidate()  //<-- cause a paint event
pBar.Value = j
If j Mod 5 = 0 Then pBar.Invalidate()
pBar.Value = j;
if (j % 5 == 0) pBar.Invalidate();