How to set StopWatch count multiple times in C# - c#

Here is my code when click a button in C# WinForm:
private void aesactive_Click(object sender, EventArgs e)
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Reset();
stopWatch.Start();
string original = textBox4.Text;
using (var random = new RNGCryptoServiceProvider())
{
string inputkey = textBox5.Text;
byte[] key = Encoding.ASCII.GetBytes(inputkey);
random.GetBytes(key);
byte[] encrypted = EncryptStringToBytes_Aes(original, key);
}
stopWatch.Stop();
textBox6.Text = stopWatch.ElapsedMilliseconds.ToString() + " ms ";
}
But when I click that button twice, or more, the results always 0 ms. Can anybody explain to me the reasons ? Thanks a lot.

If you would like to accumulate time, move Stopwatch variable outside the method, and remove the call to Reset():
private readonly Stopwatch stopWatch = new Stopwatch();
private void aesactive_Click(object sender, EventArgs e) {
stopWatch.Start();
...
stopWatch.Stop();
textBox6.Text = stopWatch.ElapsedMilliseconds.ToString() + " ms ";
}
Now that adding time is a "one-way street," consider adding a button to reset the stopwatch:
private void aesreset_Click(object sender, EventArgs e) {
stopWatch.Reset();
}
Note: Modern CPUs are capable of running millions instructions per millisecond, so it may require you to click the button many times for the value in textBox6 to move off zero.

Related

Automatically send text every 10 seconds

I have a program that gets the app name, place them on a listbox and sends them to the other window if you click the send button.
What I wanted to know is, is it possible for it to automatically send every 10 seconds after a single click on the send button? If yes, how can I possibly do that?
There's the codes, in case if it brings of any help.
private void cmd_send_Click_1(object sender, EventArgs e)
{
String processID = "";
String processName = "";
String processFileName = "";
String processPath = "";
string hostName = System.Net.Dns.GetHostName();
listBox1.BeginUpdate();
try
{
for (int i = 0; i < listBox1.Items.Count; i++)
{
piis = GetAllProcessInfos();
try
{
// String pno = textBox4.Text.ToString();
// String path = textBox5.Text.ToString();
// String name = textBox6.Text.ToString();
// String user = textBox7.Text.ToString();
// output.Text += "\n Sent data : " + pno + " " + user + " " + name + " " + path ;
processID = piis[i].Id.ToString();
processName = piis[i].Name.ToString();
processFileName = piis[i].FileName.ToString();
processPath = piis[i].Path.ToString();
output.Text += "\n\nSENT DATA : \n\t" + processID + "\n\t" + processName + "\n\t" + processFileName + "\n\t" + processPath + "\n";
}
catch (Exception ex)
{
wait.Abort();
output.Text += "Error..... " + ex.StackTrace;
}
NetworkStream ns = tcpclnt.GetStream();
String data = "";
//data = "--++" + " " + textBox4.Text + " " + textBox5.Text + " " + textBox6.Text + " " + textBox7.Text;
data = "--++" + " " + processID + " " + processPath + " " + processFileName + " " + hostName;
if (ns.CanWrite)
{
byte[] bf = new ASCIIEncoding().GetBytes(data);
ns.Write(bf, 0, bf.Length);
ns.Flush();
}
}
}
finally
{
listBox1.EndUpdate();
}
}
Any help would be greatly appreciated.
You could place your code inside a single method, call that method initially on button click and start/stop your timer depending on it's current state.
private Timer _timer;
public Form() // Initialize timer in your form constructor
{
InitializeComponent();
_timer = new Timer();
_timer.Interval = 10000; // miliseconds
_timer.Tick += _timer_Tick; // Subscribe timer to it's tick event
}
private void _timer_Tick(object sender, EventArgs e)
{
SendData();
}
private void cmd_send_Click_1(object sender, EventArgs e)
{
if (!_timer.Enabled) // If timer is not running send data and start refresh interval
{
SendData();
_timer.Enabled = true;
}
else // Stop timer to prevent further refreshing
{
_timer.Enabled = false;
}
}
private void SendData()
{
// Your code here
}
EDIT:
If you're using .NET framework 4.5 or above you can do the same thing in using async/await.
private bool keepRefreshing;
private async void cmd_send_Click_1(object sender, EventArgs e)
{
if (keepRefreshing)
{
keepRefreshing = false;
return;
}
keepRefreshing = true;
while (keepRefreshing)
{
// Your code here
await Task.Delay(10000);
}
}
On button click it will send data and it will keep sending with delay of 10 seconds. When you press the button second time it will stop refreshing interval, third time it will start again and so on..
// Declare a timer
Timer tmr = new Timer();
tmr.Interval = 10000; // 10 second
tmr.Tick += timerHandler; // We'll write it in a bit
tmr.Start(); // The countdown is launched!
private void timerHandler(object sender, EventArgs e) {
// Here the code what you need each 10 seconds
tmr.Stop(); // Manually stop timer, or let run indefinitely
}
Their are many ways one is follow.
private void cmd_send_Click_1(object sender, EventArgs e)
{
bool isResend=true;
while (isResend==true)
{
// Put all your here
System.Threading.Thread.Sleep(10000);
}
}
Other ways are using Timer, etc...
Everyone's answer is cool, but as for me if you really need that "click" as start, i'll do it this way.
Initiate events for timer & background worker inside form load.
set timer.start(); inside click.
Once ticking, if backgroundworker is not busy, execute background worker.
Ensure that you don't directly set label1.text = "send some works here." inside the background worker, it will cause error.
Hope this helps.

C# Backgroundworker download progress in label, get bytes in label

I've created an application that patches my game servers files.
However, I've got 3 problems which I can't solve:
When downloading a new patch, it doesn't update the progressbar instantly, but refreshes it after around 30-40 seconds
I want a label to show how much mega bytes they are downloading, and how much they have so far (for example: 122Mb/750Mb
When downloading, I want a label to show ~% of how much it has downloaded so far
I am not sure how to add number 2 and 3, and the number 1 problem just seems ridiculous, because there's nothing that indicates it should refresh after 30-40 seconds in my coding (at least as far as I know)
My backgroundWorker1_DoWork:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//Defines the server's update directory
string Server = "http://localhost/dl/game-updates/";
//Defines application root
string Root = AppDomain.CurrentDomain.BaseDirectory;
//Make sure version file exists
FileStream fs = null;
if (!File.Exists("version"))
{
using (fs = File.Create("version"))
{
}
using (StreamWriter sw = new StreamWriter("version"))
{
sw.Write("1.0");
}
}
//checks client version
string lclVersion;
using (StreamReader reader = new StreamReader("version"))
{
lclVersion = reader.ReadLine();
}
decimal localVersion = decimal.Parse(lclVersion);
//server's list of updates
XDocument serverXml = XDocument.Load(#Server + "Updates.xml");
//The Update Process
foreach (XElement update in serverXml.Descendants("update"))
{
string version = update.Element("version").Value;
string file = update.Element("file").Value;
decimal serverVersion = decimal.Parse(version);
string sUrlToReadFileFrom = Server + file;
string sFilePathToWriteFileTo = Root + file;
if (serverVersion > localVersion)
{
Uri url = new Uri(sUrlToReadFileFrom);
System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
response.Close();
Int64 iSize = response.ContentLength;
Int64 iRunningByteTotal = 0;
using (System.Net.WebClient client = new System.Net.WebClient())
{
using (System.IO.Stream streamRemote = client.OpenRead(new Uri(sUrlToReadFileFrom)))
{
using (Stream streamLocal = new FileStream(sFilePathToWriteFileTo, FileMode.Create, FileAccess.Write, FileShare.None))
{
int iByteSize = 0;
byte[] byteBuffer = new byte[iSize];
while ((iByteSize = streamRemote.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
{
streamLocal.Write(byteBuffer, 0, iByteSize);
iRunningByteTotal += iByteSize;
double dIndex = (double)(iRunningByteTotal);
double dTotal = (double)byteBuffer.Length;
double dProgressPercentage = (dIndex / dTotal);
int iProgressPercentage = (int)(dProgressPercentage * 100);
backgroundWorker1.ReportProgress(iProgressPercentage);
}
streamLocal.Close();
}
streamRemote.Close();
}
}
//unzip
using (ZipFile zip = ZipFile.Read(file))
{
foreach (ZipEntry zipFiles in zip)
{
zipFiles.Extract(Root + "\\", true);
}
}
//download new version file
WebClient webClient = new WebClient();
webClient.DownloadFile(Server + "version.txt", #Root + "version");
//Delete Zip File
deleteFile(file);
}
}
}
My backgroundWorker1_ProgressChanged:
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
label1.Text = "Downloading updates...";
}
And my backgroundWorker1_RunWorkerCompleted:
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
settings_btn.Enabled = true;
start_btn_disabled.Enabled = false;
start_btn_disabled.Visible = false;
start_btn.Visible = true;
start_btn.Enabled = true;
progressBar1.Value = 100;
label1.Text = "Client is up to date!";
}
Also, a side note: I'm also having a bit problems of updating labels in backgroundWorker2_DoWork?
Any ideas?
Here's some working code which updates a label on Form1 using the BackgroundWorker.
Create a new Windows Form project and drop it in your code and it'll work.
It's super ugly, but it works.
After that, just plug your code into the DoWork method and calculate your value and send to ReportProgress.
Keep in mind that the work done in DoWork method is the actual Background Thread.
That means that in that method (DoWork) you cannot access UI (form) elements because they are on the UI thread.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
backgroundWorker1.DoWork += backgroundWorker1_DoWork;
backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
}
void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
button1.Enabled = true;
}
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
backgroundWorker1.RunWorkerAsync();
}
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = e.ProgressPercentage.ToString();
}
void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
FakeCountingWork();
}
private void FakeCountingWork()
{
int totalNumber = 100;
int progressCounter = 0;
while (progressCounter < totalNumber)
{
int fakecounter = 0;
for (int x = 0; x < 100000000; x++)
{
fakecounter++;
}
progressCounter++;
backgroundWorker1.ReportProgress(progressCounter);
}
}
}
################################## EDITED TO ADD OTHER FUNCTIONALITY
Okay, here's how you can implement a label which displays the number of bytes downloaded so far.
Add a second label named label2 to your form.
Next alter the following methods from my previous example.
Here we are going to use the UserState to pass an extra value to the ProgressChanged Event. It's very simple. You can see that I'm generating a random number and it will now appear in Label2. This is where you could show your number of bytes.
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = e.ProgressPercentage.ToString();
label2.Text = e.UserState.ToString();
}
private void FakeCountingWork()
{
int totalNumber = 100;
int progressCounter = 0;
Random rnd = new Random();
while (progressCounter < totalNumber)
{
int fakecounter = 0;
for (int x = 0; x < 100000000; x++)
{
fakecounter++;
}
progressCounter++;
updateValue = rnd.Next();
backgroundWorker1.ReportProgress(progressCounter,updateValue);
}
}
I would imagine this is because you are trying to update UI objects on a different thread. HAve you tried using the Dispatcher if using wpf? https://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.invoke(v=vs.110).aspx
or Invoke if using Winforms? https://msdn.microsoft.com/fr-ca/library/zyzhdc6b(v=vs.85).aspx
Edit:
As #daylight pointed out to be, the UI was being updated in the progresschanged event, which executes on the thread which created the background worker, therefore there shouldn't be an issue regarding threading. See https://msdn.microsoft.com/en-us/library/ka89zff4(v=vs.110).aspx for more info

Awesomium freezes / not responding

I have a traffic exchange website and I want to convert it into an windows application using C# winform with Awesomium 1.7.5.
The basic setup is ready but there is a problem with Awesomium.
After visiting a few websites slows down and the freezes entirely ( Not Responding ).
public Form1()
{
InitializeComponent();
Text = "Traffic Exchange";
WindowState = FormWindowState.Maximized;
timer1 = new System.Windows.Forms.Timer();
timer1.Tick += new EventHandler(timer1_Tick);
int user_id = Properties.Settings.Default.user_id;
string user_id_s = user_id.ToString();
toolStripLabel2.Text = user_id_s;
if (Properties.Settings.Default.user_id == 0)
{
toolStripLabel3.Visible = true;
toolStripButton3.Visible = false;
}
else
{
toolStripButton3.Visible = true;
toolStripLabel3.Visible = false;
}
}
private void toolStripButton3_Click_1(object sender, EventArgs e)
{
// starting the traffic traffic exchange
LoadUrl();
StartTimer();
}
private void LoadUrl()
{
try
{
string MyConnection2 = "*******";
string Query = "select * from ****** where status = 1 AND credits > 5 ORDER BY rand() LIMIT 1";
MySqlConnection MyConn2 = new MySqlConnection(MyConnection2);
MySqlCommand MyCommand2 = new MySqlCommand(Query, MyConn2);
MyConn2.Open();
using (MySqlDataReader DR = MyCommand2.ExecuteReader())
{
while (DR.Read())
{
string WebURL = Convert.ToString(DR.GetValue(*));
string WebSurfSec = Convert.ToString(DR.GetValue(*));
int result = Convert.ToInt32(WebSurfSec);
int sec_to_mil = result * 1000;
toolStripLabel5.Text = WebSurfSec;
//toolStripStatusLabel2.Text = result.ToString();
//toolStripStatusLabel3.Text = sec_to_mil.ToString();
webControl3.Source = new Uri(WebURL);
toolStripTextBox1.Text = WebURL;
toolStripLabel6.Text = toolStripTextBox1.Text;
timer1.Interval = sec_to_mil; // in miliseconds
}
}
MyConn2.Close();
// WebCore.ReleaseMemory();
// webControl3.Update();
// Thread.Sleep(500);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void timer1_Tick(object sender, EventArgs e)
{
LoadUrl();
}
private void StartTimer()
{
timer1.Start();
}
So LoadUrl() it's a loop. When the app is started loads in the traffic exchange website, a little bit slow but it works and you can go form a page to another without freezing but when the exchange is in action ( LoadUrl() ) after 5 minutes the app is dead.
I've been searching for a solution all day and ended up with nothing, couldn't find a solution the problem.
The timer should not be recreated each time you loop. What is happening is that you are creating multiple event handlers each time you loop. Creating the handler once in the constructor and starting the timer in the button click routine is the right way.
You can change the interval inside the loop, but avoid adding another Start() method call there.

Background Worker to populate combobox in windows form application

I want to implement background worker in my windows application.
Currently I am using button event handler to load the combo box with data. As the query hangs the user interface, i would like to implement background worker as that the query runs in different thread. I have never used this background worker in any of my application. I did some research on this and still unable to implement this. Any help or advice will be greatly appreciated.
This is how my button event handler looks like
private void button6_Click(object sender, EventArgs e)
{
if (comboBox1.SelectedItem.ToString() == "All")
{
findAllUser();
}
else
{
//Do Something!!!
}
}
findAllUser() will fetch all the user from active directory which normally takes time and makes the UI unresponsive. Code for findAllUser() looks like this.
public void findAllUser()
{
System.DirectoryServices.DirectoryEntry entry = new System.DirectoryServices.DirectoryEntry("LDAP://DC=xyz, DC=com");
System.DirectoryServices.DirectorySearcher mySearcher = new System.DirectoryServices.DirectorySearcher(entry);
mySearcher.Filter = "(&(objectClass=user))";
foreach (System.DirectoryServices.SearchResult resEnt in mySearcher.FindAll())
{
try
{
System.DirectoryServices.DirectoryEntry de = resEnt.GetDirectoryEntry();
comboBox2.Items.Add(de.Properties["GivenName"].Value.ToString() + " " + de.Properties["sn"].Value.ToString() + " " + "[" + de.Properties["sAMAccountName"].Value.ToString() + "]");
}
catch (Exception)
{
// MessageBox.Show(e.ToString());
}
}
}
Below is how the background worker looks now..all empty
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
Any advice how can i implement the code above so that the background worker will populate the combobox2 with the active directory user list.
The easiest way would be to have your findAllUser method build a list of items that need to be added to the combo box, and then have the RunWorkerCompleted method populate the combo box. For example, modify your findAllUser like this:
private List<string> items;
public void findAllUser()
{
items = new List<string>();
System.DirectoryServices.DirectoryEntry entry =
new System.DirectoryServices.DirectoryEntry("LDAP://DC=xyz, DC=com");
System.DirectoryServices.DirectorySearcher mySearcher =
new System.DirectoryServices.DirectorySearcher(entry);
mySearcher.Filter = "(&(objectClass=user))";
foreach (System.DirectoryServices.SearchResult resEnt in mySearcher.FindAll())
{
try
{
System.DirectoryServices.DirectoryEntry de = resEnt.GetDirectoryEntry();
items.Add(de.Properties["GivenName"].Value.ToString() + " " +
de.Properties["sn"].Value.ToString() + " " + "[" +
de.Properties["sAMAccountName"].Value.ToString() + "]");
}
catch (Exception)
{
// MessageBox.Show(e.ToString());
}
}
}
Then, have your DoWork call findAllUser to do the actual work.
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
findAllUser();
}
And finally, have your RunWorkerCompleted populate the combo box:
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
foreach (var item in items)
{
comboBox2.Items.Add(item);
}
}
If you want to show progress, then you need to call ReportProgress from time to time while the worker is doing its business. Since you don't know exactly how long the process will take or exactly how many users it will find, you can't really report accurate progress. In that case, you have to guess. Since you say it takes "like 30 seconds," then you can use that as the 100% mark. So you start a StopWatch when the worker starts its processing, and update every half second or so. Modify your findAllUser function like this:
public void findAllUser()
{
const int ExpectedTime = 30000; // 30,000 milliseconds
// stopwatch keeps track of elapsed time
Stopwatch sw = Stopwatch.StartNew();
// Create a timer that reports progress at 500 ms intervals
System.Timers.Timer UpdateTimer;
UpdateTimer = new System.Threading.Timer(
null,
{
var percentComplete = (100 * sw.ElapsedMilliseconds) / ExpectedTime;
if (percentComplete > 100) percentComplete = 100;
ReportProgress(percentComplete);
// Update again in 500 ms if not already at max
if (percentComplete < 100)
UpdateTimer.Change(500, Timeout.Infinite);
}, 500, Timeout.Infinite);
items = new List<string>();
// rest of findAllUser here
// dispose of the timer.
UpdateTimer.Dispose();
}
And then, in your ProgressChanged event handler, update your progress bar.
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// Update the progress bar with the value from e.ProgressPercentage
}
Again, because you don't know exactly how long things are going to take, you make an estimate. Above, I estimated 30 seconds, and the code blindly assumes that if 15 seconds have gone by, then it's half done.
Note that I create the timer as a one-shot and re-initialize it after every tick. I do this because I want to prevent concurrent updates. The timer fires on a separate thread, and the ReportProgress method marshals the call to the ProgressChanged event to the UI thread. If the UI thread is busy with other things, then another timer event could come in and you could end up with a bunch of threads all trying to marshal calls to the UI. Probably not a problem in this case because we're only talking a maximum of 60 calls (two calls per second for 30 seconds), but in general it's a good idea to prevent that kind of thing from happening.
Place your code on the backgroundWorker1_DoWork. But I suggest you either use Thread or Task Parallel Library
If you're on .NET 4.0, use the TPL.
You can do it like this:
Task runner = new Task(() =>
{
// do process here
});
runner.Start();
of if you're on older frameworks, use the Thread like this.
Thread thread = new Thread(() =>
{
// do process here
});
thread.IsBackground = true;
thread.Start();
read more about the TPL and Thread.
Using BackgroundWorker is convenient because it automagically invokes the ProgressChanged and RunworkerCompleted event handlers in the UI thread. You can use it like below.
private void AddItem(DirectoryEntry de)
{
comboBox2.Items.Add(de.Properties["GivenName"].Value.ToString() + " " + de.Properties["sn"].Value.ToString() + " " + "[" + de.Properties["sAMAccountName"].Value.ToString() + "]");
}
private void button6_Click(object sender, EventArgs e)
{
if (comboBox1.SelectedItem.ToString() == "All")
{
this.backgroundWorker1.RunWorkerAsync();
}
else
{
//Do Something!!!
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// Bind to the users container.
DirectoryEntry entry = new DirectoryEntry("LDAP://CN=xyz,DC=com");
// Create a DirectorySearcher object.
DirectorySearcher mySearcher = new DirectorySearcher(entry);
try
{
// Create a SearchResultCollection object to hold a collection of SearchResults
// returned by the FindAll method.
SearchResultCollection result = mySearcher.FindAll();
int count = result.Count;
for(int i = 0; i < count; i++)
{
SearchResult resEnt = result[i];
try
{
DirectoryEntry de = resEnt.GetDirectoryEntry();
BeginInvoke(new Action<DirectoryEntry>(AddItem), de);
}
catch (Exception)
{
// MessageBox.Show(e.ToString());
}
this.backgroundWorker1.ReportProgress(i / count);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.progressBar1.Value = e.ProgressPercentage;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.progressBar1.Value = 100;
}
You can use below logic to implement background worker for your code.
var startListenerWorker = new BackgroundWorker();
startListenerWorker.DoWork += new DoWorkEventHandler(this.StartListenerDoWork);
startListenerWorker.RunWorkerAsync();
private void StartListenerDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
// Your logic to load comboBox will go here for running your query
}
you can also implement thread to have your logic run on a separate thread.

How to Add Custom Time Format?

I am making a NetcafeProgram in C# and I want to get the current DateTime. I want my output like this (hr.mins)"0.25". I have the current DateTime but I want to show it like this (hr.mins)"0.25" in the labelTime_1 but it is not working. This is the command which I used
starttime_1 = DateTime.Now.ToString("h:mm:ss tt");
and I changed it to
starttime_1 = DateTime.Now.ToString("h.mm");
and then I wanted to get the duration like this
TimeSpan duration = DateTime.Parse(endtime_1).Subtract(DateTime.Parse(starttime_1));
but it gives me errors.
Here is a Screenshot of My Formv:
I want the time to get posted On that Time Elapsed Label but it doesn't work. Here is the coding of BtnStop1
private void btnStop_1_Click(object sender, EventArgs e)
{
//string duration = Convert.ToInt32(((starttime_1) - (endtime_1)));
gbx_1.BackColor = Color.LimeGreen;
btnStop_1.Enabled = false;
//endtime_1 = DateTime.Now.ToString("h:mm:ss tt");
//TimeSpan duration = DateTime.Parse(endtime_1).Subtract(DateTime.Parse(starttime_1));
endtime_1 = DateTime.Now.ToString("h.mm tt");
TimeSpan duration = DateTime.Parse(endtime_1).Subtract(DateTime.Parse(starttime_1));
lblTime_1.Text = Convert.ToString(duration);
string var = "Cabin One is Free";
btnStart_1.Enabled = true;
HP_1.Enabled = true;
CR_1.Enabled = true;
reader = new SpeechSynthesizer();
reader.SpeakAsync(var);
}
Coding of BtnStart
private void btnStart_1_Click(object sender, EventArgs e)
{
gbx_1.BackColor = Color.Red;
btnStart_1.Enabled = false;
//starttime_1 = DateTime.Now.ToString("h:mm:ss tt");
starttime_1 = DateTime.Now.ToString("h.mm tt");
lblTime_1.Text = "CountingTime";
string var = "Cabin One is Occupied";
reader = new SpeechSynthesizer();
reader.SpeakAsync(var);
HP_1.Enabled = false;
CR_1.Enabled = false;
}
Here Are My Variables
public string starttime_1;
public string starttime_2;
public string starttime_3;
public string starttime_4;
public string starttime_5;
public string starttime_6;
public string endtime_1;
public string endtime_2;
public string endtime_3;
public string endtime_4;
public string endtime_5;
public string endtime_6;
I would strongly suggest changing your variable types to DateTime?. It is better to store data in its native type and then do the convert to string on display. This way, when you want the duration, you are not parsing back to DateTime. You can handle any rounding you want on the base data.
So, your conversion to string should be at the highest level of you stack. It will keep your code cleaner and make it easier to refactor the logic away from the UI later if appropriate.
Not really sure I understand all this parsing but if you're just trying to record start and stop times and output a timespan I would do as Jon Skeet recommend with the stopwatch. Something along these lines looks like what you're going for but a bit cleaner.
// Build stopwatch and lists
Stopwatch sw = new Stopwatch();
List<string> startTimes = new List<string>();
List<string> endTimes = new List<string>();
private void startBtn_Click(object sender, EventArgs e)
{
// Start stopwatch and record start time
sw.Start();
startTimes.Add(DateTime.Now.ToString("h.mm"));
}
private void stopBtn_Click(object sender, EventArgs e)
{
// Stop stopwatch
sw.Stop();
// Record stop time and reset stopwatch
endTimes.Add(DateTime.Now.ToString("h.mm"));
sw.Reset();
// Output timespan
outputLbl.Text = sw.Elapsed.ToString();
}

Categories