foreach循环中的进度条

时间:2013-12-09 16:13:01

标签: c# winforms

我有一种方法可以迭代一系列音乐笔记并一个接一个地播放它们。我创建了一个进度条,它将显示foreach循环的状态。 问题是进度条没有达到100%但大约达到85%。我还注意到进度条大致进展,我认为这可能是因为步骤很大。关于如何优化此进度条的任何想法,pb是我的进度条实例,谢谢

    public void PlayAll()
    {
        pb.Maximum = Convert.ToInt32(CountTotalDuration());  //Total lenght of the full song.
        pb.Step = Convert.ToInt32(CountTotalDuration()) / Convert.ToInt32(ListSize()); //Total lenght of each note making up the song.
        foreach (MusicNote m in list)
        {
            m.sp.Stop();
            m.sp.Play();
            Thread.Sleep(m.NoteDuration*100);
            pb.PerformStep();
        }
    }

2 个答案:

答案 0 :(得分:3)

您的问题来自于您的步骤中的舍入错误。让我们看一个简单的例子,假设你有CountTotalDuration() 100ListSize() 7

因为您有两个整数/执行整数除法并抛弃任何余数,因此100 / 7等于14(而不是14.285714且重复285714 。这使得您的步长为14,因此在完成7个步骤后,您达到的总值为98,您将在工具栏上看到98%。

由于CountTotalDuration()似乎是NoteDuration的总和,解决这个问题的方法是每步不使用相等的步长。相反,只需将最大值设置为总持续时间,并通过手提箱持续时间增加条形。这将使条形按照音符长度与乐曲中的位置成比例跳跃。

public void PlayAll()
{
    pb.Maximum = Convert.ToInt32(CountTotalDuration());  //Total lenght of the full song.
    int currentCount = 0; //Initialize our counter to 0.

    foreach (MusicNote m in list)
    {
        m.sp.Stop();
        m.sp.Play();
        Thread.Sleep(m.NoteDuration*100);

        //Increment the counter proportional to the length of the note.
        currentCount += m.NoteDuration;

        //Set the progress bar using our calculated position.
        pb.Value = currentCount;
    }
}

当长音符播放时,你仍然会有很大的跳跃,解决这个问题的唯一方法就是不使用Thread.Sleep(m.NoteDuration*100);而是使用多个较短的暂停并在这些暂停之间更新条形码。另外Thread.Sleep可能不是暂停循环的最佳方法,但我不知道最好的替代方法是什么,这取决于你没有与我们分享的很多细节。


您可能也会对旧方法有类似的行为,并且对于每个播放的音符都会使音符跳过1,并使条形的最大值等于您将播放的音符数。

public void PlayAll()
{
    pb.Maximum = list.Length; //Or equivalent, perhaps ListSize()?
    pb.Step = 1;

    foreach (MusicNote m in list)
    {
        m.sp.Stop();
        m.sp.Play();
        Thread.Sleep(m.NoteDuration*100);
        pb.PerformStep();
    }
}

这样可以为每个音符提供更均匀的跳跃,但如果这首歌只有几个音符,那么即使跳跃也可能非常大。

答案 1 :(得分:1)

听起来很奇怪,我没有发现问题,但我建议你可以这样试试:

public void PlayAll()
    {
        pb.Maximum = Convert.ToInt32(ListSize());  //Total lenght of the full song.
        pb.Step = 1;
        int i = 1;
        foreach (MusicNote m in list)
        {
            m.sp.Stop();
            m.sp.Play();
            Thread.Sleep(m.NoteDuration * 100);
            pb.Value = i++;
        }
    }

更进一步,也许你应该使用多线程来改善用户体验,因为Thread.Sleep()使表单像死的一样。