How to calculate the time remaining to complete an operation? - c#

This is what I have so far, but it doesn't matter to what number I change the progressbar1.value is changed too, I still get the same result 0. I am guessing that the problem lies in the timespent Variable, but I can't figure it out.
using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
int sum = 0;
for (int i = 1; i <= 100; i++)
{
// run the process here
Thread.Sleep(100);
// end process
sum = sum + i;
backgroundWorker1.ReportProgress(i);
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
backgroundWorker1.ReportProgress(0);
return;
}
}
// displays the sum of the process
e.Result = sum;
}
private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
label5.Text = e.ProgressPercentage.ToString() + "%";
DateTime starttime = DateTime.Now;
var timespent = DateTime.Now - starttime;
double secondsremaining = (double)(timespent.TotalSeconds / progressBar1.Value) * (progressBar1.Maximum - progressBar1.Value);
label7.Text = "Time remaining:" + (int)secondsremaining;
Console.WriteLine(secondsremaining);
}
private void backgroundWorker1_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
label5.Text = "Processing Cancelled";
}
else if (e.Error != null)
{
label5.Text = e.Error.Message;
}
else
{
label5.Text = "Sum = " + e.Result.ToString();
}
label6.Text = "";
}
private void button11_Click_1(object sender, EventArgs e)
{
//Checks if the background worker is busy running operations
if (!backgroundWorker1.IsBusy)
{
//this method will start the excution of the opreation
backgroundWorker1.RunWorkerAsync();
}
else
{
label6.Text = "The operation is being completed, please wait...";
}
}
}
}
}

The code you have is reasonably close, but you have a mistake: your starttime variable is a local variable, which you reset to the current time immediately before trying to use it to compute the elapsed time. Thus, the elapsed time is always zero, or very close to.
You should move the variable to be an instance field, so that it can persist between the progress updates:
DateTime starttime;
private void backgroundWorker1_DoWork(
object sender, System.ComponentModel.DoWorkEventArgs e)
{
int sum = 0;
// Using UtcNow will ensure the time calculation is correct even if
// the work occurs during a daylight saving time change-over
starttimme = DateTime.UtcNow;
for (int i = 1; i <= 100; i++)
{
// run the process here
Thread.Sleep(100);
// end process
sum = sum + i;
backgroundWorker1.ReportProgress(i);
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
backgroundWorker1.ReportProgress(0);
return;
}
}
// displays the sum of the process
e.Result = sum;
}
private void backgroundWorker1_ProgressChanged(
object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
label5.Text = e.ProgressPercentage.ToString() + "%";
var timespent = DateTime.UtcNow - starttime;
// Casting to double here is superfluous. TotalSeconds is already a
// double, and its presence in the expression results in the rest of
// the values being promoted to double and the expression type being double.
double secondsremaining =
(double)(timespent.TotalSeconds / progressBar1.Value) *
(progressBar1.Maximum - progressBar1.Value);
label7.Text = "Time remaining:" + (int)secondsremaining;
Console.WriteLine(secondsremaining);
}

Try this one.
public static void Main(string[] args)
{
DateTime StartTime = DateTime.Now;
/// do something here... that actually takes time
Thread.Sleep(TimeSpan.FromSeconds(1));
/// next estimate update
{
double WorkDone = 0.10; // e.g. 10%... give some indication how much work has been done between 0 and 1
TimeSpan TimeSpent = DateTime.Now - StartTime;
TimeSpan TimeOverall = TimeSpan.FromTicks((long) (TimeSpent.Ticks / WorkDone));
TimeSpan TimeRemaining = TimeOverall - TimeSpent;
Console.WriteLine(TimeRemaining.TotalSeconds);
}
}
The DateTime.Now resolution is in Ticks or 1E-7 seconds, if you request the time too often then no time has passed. For higher resolution you need performance counters that can measure CPU cycles.

Related

How to calculate time difference (subtract time) in C#?

I am creating program to measure vacuum value with Arduino and display it in the form that created with C#.
I want to store time as an constant. It is starting time of the program. I assigned it with "Connect" button. When I clicked, time value is storing.
Then I am using "timer tick" method to see measured values instantly. Also, DateTime.Now shows me instant system time. It is changing like a clock.
click here to see the picture
Here is the Connect button's code;
public void button1_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
try
{
if (comboBox1.Text == "")
{
MessageBox.Show("Please select the port name!");
}
else
{
serialPort1.PortName = comboBox1.Text;
serialPort1.ReadBufferSize = 8;
serialPort1.Open();
timeval.Clear();
button1.Enabled = false;
button2.Enabled = true;
timer1.Start();
DateTime myDateTime = DateTime.Now; //It stores the instant time information when button is clicked.
label14.Text = myDateTime.ToString(); // shows in the label
//serialPort1.ReadTimeout = 300;
}
}
catch (UnauthorizedAccessException)
{
MessageBox.Show("Unauthorized Access!");
}
}
Here is the timer tick's code;
public void timer1_Tick(object sender, EventArgs e)
{
label12.Text = DateTime.Now.ToString();
//TimeSpan time_difference = DateTime.Now - myDateTime; // trying to calculate time difference.
//double saniye = time_difference.Seconds;
//double dakika = time_difference.Minutes;
//label10.Text = (Math.Round(saniye)).ToString();
//label16.Text = (Math.Round(dakika)).ToString();
new_data = 756 * (float.Parse(data) - 1023) / 1023;
sensorval.Add(Math.Round(new_data, 1));
all_data.Add(Math.Round(new_data, 1));
textBox1.Text = Convert.ToString(Math.Round(new_data, 2));
all_data.Sort();
var peak_vacuum = all_data[0];
textBox4.Text = peak_vacuum.ToString();
if (sensorval.Count % 100 == 0)
{
sensorval.Sort();
var find_max = sensorval[0];
var find_min = sensorval[sensorval.Count - 1];
textBox3.Text = find_min.ToString();
textBox2.Text = find_max.ToString();
sensorval.RemoveRange(0, 99);
}
}
I could not calculate time difference because myDateTime variable is calculating in button2 and defined in button2 method. But DateTime.Now is defined in timer tick method. So, I am getting an error that "The name 'myDateTime' does not exist in the current content." in the timer tick method.
By the way, I tried to use counter in the timer tick to see the seconds after program works. It was not so accurate. It was slower then the real time. So, I choose above method.
Thank you in advance.
I thinks its like what you want.
public partial class Form1 : Form
{
// accessable from all methods, events on Form1
private DateTime myDateTime;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
myDateTime = DateTime.Now;
// other codes
}
private void timer1_Tick(object sender, EventArgs e)
{
// other codes
}
private void button2_Click(object sender, EventArgs e)
{
// other codes
var diffrenceSpan = DateTime.Now - myDateTime;
var hours = diffrenceSpan.Hours;
var minutes = diffrenceSpan.Minutes;
var seconds = diffrenceSpan.Seconds;
}
}
gits project links

How To Make a StopWatch With C#

I just want to ask that if I can make a stopwatch with C# I tried:
private void button2_Click(object sender, EventArgs e)
{
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
int st = 00;
int m = 00;
string stime = "00:00";
if(st == 60)
{
m++;
st = 00;
}
else
{
st++;
}
if (m == 60)
{
m = 00;
}
if(st < 10)
{
st = 0 + st;
}
if(m < 10)
{
m = 0 + m;
}
stime = m.ToString() + ":" + st.ToString();
label3.Text = stime;
}
this but it didn't worked. My timer is setted up and the interval of the timer is 1000ms. Can someone help me?
It looks to me, that you are more likly to make a watch rather than a stopwatch?
If you're making a stopwatch, I think you need a field/property in your class that holds the starting time:
private DateTime _start;
private void button2_Click(object sender, EventArgs e)
{
_start = DateTime.Now;
timer1.Start();
}
and then in timer1_Tick you can do:
private void timer1_Tick(object sender, EventArgs e)
{
TimeSpan duration = DateTime.Now - _start;
label3.Text = duration.ToString(<some format string>);
}
It seems that your current code in timer1_Tick only has local variables and therefore always will produce the same time? :-)

How to display seconds using TimeSpan on Timer Tick Event

I am using below code to display time left in hh:mm:ss format for example if duration is 30min, it will show like this 00:30:00 and after 1 min it will show 00:29:00, how can i also display the remaining seconds and decrease them accordingly.,
Edit
I tried timer1.Interval = 1000; and
examTime = examTime.Subtract(TimeSpan.FromSeconds(1));
But its not showing me seconds reducing each second, How do i do it ?
public SubjectExamStart()
{
InitializeComponent();
examTime = TimeSpan.FromMinutes(double.Parse(conf[1]));
label1.Text = examTime.ToString();
timer1.Interval = 60 * 1000;
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
if (sender == timer1)
{
if (examTime.TotalMinutes > 0)
{
examTime = examTime.Subtract(TimeSpan.FromMinutes(1));
label1.Text = examTime.ToString();
}
else
{
timer1.Stop();
MessageBox.Show("Exam Time is Finished");
}
}
}
Instead of Subtracting TimeSpan.FromMinutes you need to subtract from TimeSpan.FromSeconds
public SubjectExamStart()
{
InitializeComponent();
examTime = TimeSpan.FromSeconds(double.Parse(conf[1]));
label1.Text = examTime.ToString();
timer1.Interval = 1000;
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
if (sender == timer1)
{
if (examTime.TotalMinutes > 0)
{
examTime = examTime.Subtract(TimeSpan.FromSeconds(1));
label1.Text = examTime.ToString();
}
else
{
timer1.Stop();
MessageBox.Show("Exam Time is Finished");
}
}
}
If you want to format the Time Span value while assigning to Label... You can use below..
label1.Text = examTime.ToString(#"dd\.hh\:mm\:ss");
To do this properly, you will need to keep a track of when the timer was started
DateTime examStartTime;
System.Windows.Forms.Timer runTimer;
TimeSpan totalExamTime = new TimeSpan(1, 30, 0); // Set exam time to 1 hour 30 minutes.
if (runTimer == null)
runTimer = new System.Windows.Forms.Timer();
runTimer.Interval = 200;
runTimer.Tick -= new EventHandler(runTimerTick);
runTimer.Tick += new EventHandler(runTimerTick);
examStartTime = DateTime.Now;
runTimer.Start();
Then in the event handler you can do:
public void runTimerTick(object sender, EventArgs e)
{
TimeSpan currentExamTime = DateTime.Now - examStartTime;
if (currentExamTime > totalExamTime)
{
MessageBox.Show("Exam Time is Finished");
runTimer.Stop();
runTimer.Tick -= new EventHandler(runTimerTick);
runTimer.Dispose();
}
}
I hope this helps.
try this hope this will work for u
set timer interval=1000
minremain=1200000; //Should be in milisecond
timerplurg.satrt();
private void timerplurg_Tick(object sender, EventArgs e)
{
minremain = minremain - 1000; //substring One second from total time
string Sec = string.Empty;
if (minremain <= 0)
{
lblpurgingTimer.Text = "";
timerplurg.Stop();
return;
}
else
{
var timeSpan = TimeSpan.FromMilliseconds(Convert.ToDouble(minremain));
var seconds = timeSpan.Seconds;
if (seconds.ToString().Length.Equals(1))
{
Sec = "0" + seconds.ToString();
}
else
{
Sec = seconds.ToString();
}
string Totaltime = "Remaing Second: " + Sec;
lblpurgingTimer.Text = Totaltime;
}

Progress Bar run less time than defined

I created a function that gets number of milliseconds and then runs the progress bar but the result is that the progress bar run less time than defined.
this.timerProgress.Tick += new System.EventHandler(this.timerProgress_Tick);
public void AnimateProgBar(int milliSeconds)
{
if (!timerProgress.Enabled)
{
this.Invoke((MethodInvoker)delegate { pbStatus.Value = 0; });
timerProgress.Interval = milliSeconds / 100;
timerProgress.Enabled = true;
}
}
private void timerProgress_Tick(object sender, EventArgs e)
{
if (pbStatus.Value < 100)
{
pbStatus.Value += 1;
pbStatus.Refresh();
}
else
{
timerProgress.Enabled = false;
}
}
using AnimateProgBar(100), will end up creating a Interval of 1 millisecond.
timerProgress.Interval = milliSeconds; //do not divide by 100
this.timerProgress.Tick += new System.EventHandler(this.timerProgress_Tick);
public void AnimateProgBar(int milliSeconds)
{
if (!timerProgress.Enabled)
{
this.Invoke((MethodInvoker)delegate { pbStatus.Value = 0; });
timerProgress.Interval = milliSeconds; //do not divide by 100
timerProgress.Enabled = true;
}
}
private void timerProgress_Tick(object sender, EventArgs e)
{
if (pbStatus.Value < 100)
{
pbStatus.Value += 1;
pbStatus.Refresh();
}
else
{
timerProgress.Enabled = false;
}
}
A call to AnimateProgBar(1000) will result in the following calculation: 1000 / 100. That equals 10.
The Timer interval is already in milliseconds. So you're effectively setting the interval to 10ms.

Adding sum to timer

I would like to know how to create a label that adds sum + 1 every 5 seconds? I've tried with an if loop but unfortunately it resets one second later.
Thank you in advantage for your attention
using System.Diagnostics;
// using system.diagnotics voor stopwatch
namespace WindowsFormsApplication7
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private Stopwatch sw = new Stopwatch();
private void button1_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
sw.Start();
if (timer1.Enabled == true) { button1.Text = "stop"; }
else { button1.Text = "false"; sw.Stop(); }
}
private void timer1_Tick(object sender, EventArgs e)
{
int hours = sw.Elapsed.Hours;
int minutes = sw.Elapsed.Minutes;
int seconds = sw.Elapsed.Seconds;
int sum = 0;
label1.Text = hours + ":" ;
if (minutes < 10) { label1.Text += "0" + minutes + ":"; }
else { label1.Text += minutes + ":"; }
if (seconds < 10) { label1.Text += "0" + seconds ; }
else { label1.Text += seconds ; }
if (seconds ==5) { sum = sum +=1; }
label2.Text = Convert.ToString(sum);
}
}
}
sum should be a class field. Also you can use custom format string for elapsed TimeSpan.
int sum = 0;
private void timer1_Tick(object sender, EventArgs e)
{
// int sum = 0; local variable will be set to zero on each timer tick
label1.Text = sw.Elapsed.ToString(#"hh\:mm\:ss");
// btw this will not update sum each five seconds
if (sw.Elapsed.Seconds == 5)
sum++; // same as sum = sum +=1;
label2.Text = sum.ToString();
}
Your current implementation will increase sum only if current elapsed timeout's second value is five. Which could never happen (depending on your timer interval). If you have timer interval set to 1000 milliseconds, then you can increase sum on each tick, but set label2.Text = (sum % 5).ToString().
every time your stopwatch TICKS, sum is inside TICK and it will reset and start from
int sum=0;
so try to make sum variable GLOBAL outside timer1_Tick event and it will continue increasing.
You will have to move sum out of the timer callback as you are setting it to 0 each time the timer elapses
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private int sum = 0;
private DateTime lastUpdate;
private Stopwatch sw = new Stopwatch();
private void timer1_Tick(object sender, EventArgs e)
{
label1.Text = string.Format("{0:00}:{1:00}:{2:00}",
sw.Elapsed.Hours, sw.Elapsed.Minutes, sw.Elapsed.Seconds);
if (DateTime.Now >= lastUpdate.AddSeconds(5))
{
sum++;
lastUpdate = DateTime.Now;
label2.Text = sum.ToString();
}
}
private void button1_Click(object sender, EventArgs e)
{
if (timer1.Enabled == true)
{
sw.Stop();
button1.Text = "stop";
}
else
{
sum = 0;
lastUpdate = DateTime.Now;
timer1.Enabled = true;
sw.Start();
button1.Text = "Start";
}
}

Categories

Resources