2017-06-13 14 views
1

我有5个数字降序排序的数组:{289,151,69,27,6}:制作增量完成在同一时间

int[] sortedArray = new int[] { 289, 151, 69, 27, 6 }; 

和5 progressbars在窗体上。 每一个进度条的最大值= sortedArray [X]

因此,例如:

progressBar0.MaxValue = 289; //First element of array 

progressBar1.MaxValue = 151; //2nd 

progressBar3.MaxValue = 69; // etc... 

我想达成什么是使所有progressbars增量,直到它们各自的MaxValue,而且使光洁度同时

我开始为每个数组元素创建一个新的线程。但我找不到算法,以使它们一起完成。我想用TimeSpan实现一些东西。因此,例如:

所有progressbars需要5秒..

内是他们的MaxValue我怎么能这样做?

+1

您可以根据达到5秒钟的时间量来计算当前值并设置该值。 –

+1

@MightyBadaboom实际上使用你的%计算思路,他不需要5秒的限制,如果你将每个值分解成100的等级,相同数量的增量将使它们全部达到100(值可以被舍入最多占小数)。 –

+0

为什么你需要使用线程?使用一个'定时器'[如图所示](https://stackoverflow.com/questions/7259511/increase-a-progressbar-with-timer-in-winforms)。你只需要根据最大值计算'Interval'属性。例如:'timer.Interval = 5000/289' –

回答

2

当您试图在一段时间内增加它们时,您需要做的是制定一个介于0和1之间的因子,表明您完成的距离有多近(基于您开始以来已经过了多长时间)

某处记录开始时间。 var startTime = DateTime.UtcNow;在你的更新代码

那么做到这一点

var elapsedTime = DateTime.UtcNow - startTime; //How long as elapsed 
int progress = elapsedTime.TotalSeconds/5.0; //Small number/a large number is always 0..1 
if (progress > 1) 
    progress = 1; 

则进度条显示基于0..MaxValue的规模,而不是0..1自己的进步,所以你只要乘以目前的进度因素通过progressBar.MaxValue

someProgressBar.Value = (int)Math.Ceiling(someProgressBar.MaxValue * progress); 

这是完全一样的工作了百分比(每百),您只需通过100这就是你的工作了,顺便百分比乘以0..1因子(smallNumber/bigNumber)* 100.

PS:如果您按照我的建议使用绝对时间,那么您的进度条将始终在正确的时间完成。在循环中添加小增量(例如,在定时器中)的问题是,如果应用程序繁忙/滞后,那么定时器将完成得太晚。

+0

伟大的这是我一直在寻找!谢谢 :) – user3673720

1

这只是按比例增加它们的一个例子。

因此,让我们说,出于参数的原因,他们都将增加5倍。简单地将每个最大值除以5,并按每个步长递增该量。

int[] sortedArray = new int[] { 289, 151, 69, 27, 6 }; 
var incrementCount = 5.0; 
int incrementAmount = sortedArray.Select(x => Math.Ceil((float)x/incrementCount)).ToArray(); 

您现在有一个数组,每个进度条都有相应的增量步长。

0

您需要找到一些地方编写代码来增加进度条的值。

一个计时器是一个很好的选择,与Thread你不能有办法定期更新进度条。

现在让我们来创建一个计时器,它每秒钟都有一个滴答滴答,当计时器滴答时,我们更新进度条。我们选择System.Windows.Forms.Timer,因此Tick事件处理程序在UI线程上运行。

System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer(); 
myTimer.Interval = 1000; 
myTimer.Tick += (sender, e) => UpdateProgressBars(); 
myTimer.Start(); 

下一步就是计算每个进度条的值。

对于第一个ProgressBar,在第一个勾号处,值将是289/5;在第二个时间点,它将是(289/5 * 2)。

所以UpdateProgressBars方法是这样的

int counter = 0; //the counter for tick event 
private void UpdateProgressBars(object sender, EventArgs e) 
{ 
    counter++; 
    progressbar1.Value = sortedArray[0] * counter/5; 
    progressbar2.Value = sortedArray[1] * counter/5; 
    ... 
} 
0

我只考虑在这里一个值,但该解决方案能够轻松地扩展到多个值。

输入:

  • 最大值:V_max
  • 时间跨度,其中在所述端部的进展值应等于V_maxtimespan

进展值:

  • V_progress

助手:

  • 一个StopWatch跟踪的经过时间:stopwatch
  • 一个System.Timers.Timer执行每10ms定期更新:timer

当秒表的经过时间达到输入时间间隔,停止更新并将V_progress设置为V_max。否则根据经过的时间计算V_progress作为V_max的一小部分。

var V_max = 254; 
var V_progress = 0.0; 
var timespan = new TimeSpan(0, 0, 0, 5, 0); 
var stopwatch = new Stopwatch(); 
var timer = new System.Timers.Timer(10); 
timer.Elapsed += (sender, e) => 
{ 
    var elapsedMs = stopwatch.Elapsed.TotalMilliseconds; 
    var percentage = stopwatch.Elapsed.TotalMilliseconds/timespan.TotalMilliseconds; 
    if (percentage >= 1.0) 
    { 
     timer.Stop(); 
     stopwatch.Stop(); 
     percentage = 1.0; 
    } 
    // probably dispatch this assignment to the UI thread for the actual code 
    V_progress = percentage * V_max; 
    // test output 
    Console.WriteLine(V_progress); 
}; 


stopwatch.Start(); 
timer.Start(); 
0

让自己变得简单 - 使用微软的Reactive Framework(NuGet“System.Reactive.Windows.Forms”(假设这是Windows窗体))。那么你可以这样做:

ProgressBar[] progressBars = new ProgressBar[] { /* pbs here */ }; 
int[] sortedArray = new int[] { 289, 151, 69, 27, 6 }; 

var updates = 100; 
Observable 
    .Interval(TimeSpan.FromSeconds(5.0/updates)) 
    .Take(updates) 
    .Select(n => sortedArray.Select(x => x * ((int)n + 1)/updates).ToArray()) 
    .ObserveOn(this) 
    .Subscribe(x => 
    { 
     for (var i = 0; i < sortedArray.Length; i++) 
     { 
      progressBars[i].Value = x[i]; 
     } 
    }); 

我测试过这段代码,它工作得很好,据我所知。