I set up a windows form with a textbox, and two buttons, here is the click event for the buttons:
private int numberOfIterations = 1000;
private void WriteToGuiManyTimesButton_Click(object sender, EventArgs e)
{
TestTextBox.Text = string.Empty;
DateTime startTime = DateTime.Now;
for (int i = 0; i < numberOfIterations; i++)
{
TestTextBox.Text += "s";
}
DateTime endTime = DateTime.Now;
TestLabel.Text = (endTime.Ticks - startTime.Ticks).ToString();
}
private void WriteToGuiOnceButton_Click(object sender, EventArgs e)
{
TestTextBox.Text = string.Empty;
DateTime startTime = DateTime.Now;
string s = "";
for (int i = 0; i < numberOfIterations; i++)
{
s += "s";
}
TestTextBox.Text = s;
DateTime endTime = DateTime.Now;
TestLabel.Text = (endTime.Ticks - startTime.Ticks).ToString();
}
The end result is the same, the textbox has 1000 lots of "s".
However, if you prepare the string in memory, then write it to the Textbox, it only takes 9985 ticks, but if you write to the Textbox each time, it takes 1222285 ticks.
Is this because writing to TextBox.Text takes longer than writing to a variable in memory, if so, why?
The reason writing multiple times to Textbox.Text is much slower is that it is a property. The property excutes code each time it is written, potentially firing all kinds of events, such as repainting as Dmitry suggests.
Altering a string in memory simply creates a new string with the added character which seems to be much faster. Again as Dmitry suggests, using a StringBuilder would be the best choice since that would not result in a new string object being created for each modification.
It takes a lot of time for the TextBox to be re-painting in each loop itteration;
however constant string re-creating in s += "s" is not a good choice either.
Use StringBuilder as a buffer:
private void WriteToGuiManyTimesButton_Click(object sender, EventArgs e) {
DateTime startTime = DateTime.Now;
StringBuilder Sb = new StringBuilder();
for (int i = 0; i < numberOfIterations; ++i) {
Sb.Append("s");
}
TestTextBox.Text = Sb.ToString();
DateTime endTime = DateTime.Now;
TestLabel.Text = (endTime.Ticks - startTime.Ticks).ToString();
}
Related
private void button1_Click(object sender, EventArgs e)
{
backworker.RunWorkerAsync();
}
private void backworker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 10000; i++)
{
label1.Text = i.ToString();
DateTime d2 = DateTime.Now;
label2.Text = d2.ToString();
}
}
Friends i am working on comparing times between when the task of backworker finished, like how much time it tooks to finish the loop task
but when i do it, i tried to put the Comparasion after loop but it tells me error because d2 not declared
so how can i solve that to compare and get the exact time that the loop took to finish the task of printing numbers
I think this could work:
DateTime d2 = DateTime.Now;
for (int i = 0; i < 10000; i++)
{
...
}
label2.Text = (DateTime.Now - d2).ToString();
A good way to measure times is to use System.Diagnostics.Stopwatch:
var sw = Stopwatch.StartNew();
for (int i = 0; i < 10000; i++)
{
...
}
label2.Text = sw.Elapsed.ToString();
Your DateTime is declared withing the loop and therefore its scope is limited to the loop body. You must declare it before, i.e., outside, the loop to make it available after the loop. But it is better to use a Stopwatch for this purpose.
Another problem is that you are attempting to access a Control (a Label) from another thread than the UI thread. You are not allowed to do this.
Fortunately the BackgroundWorker Class can "Talk" to the UI thread through the ProgressChanged event.
Setup the BackgroundWorker with:
private void button1_Click(object sender, EventArgs e)
{
backworker.WorkerReportsProgress = true;
backworker.RunWorkerAsync();
}
Then declare another event handler which will automatically be called in the UI-thread:
private void Backworker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = e.ProgressPercentage.ToString();
var ts = (TimeSpan)e.UserState;
label2.Text = ts.ToString(#"ss\.ff");
}
Now, change you worker to
private void Backworker_DoWork(object sender, DoWorkEventArgs e)
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
for (int i = 0; i < 100; i++) {
Thread.Sleep(100);
backworker.ReportProgress(i, stopWatch.Elapsed);
}
stopWatch.Stop();
backworker.ReportProgress(100, stopWatch.Elapsed);
}
Note that I have introduced a Thread.Sleep(100); and have diminished the number of loops by 100. This is because otherwise the UI cannot display the progress that fast. In a real scenario you would replace Thread.Sleep by some useful work.
I'm new to C#.
I'm trying to make a simple task reminder program.
The problem is, when I try to add a countdown for deadline time, it won't work correctly.
My first task countdown will be overwritten by my second task countdown, the same case when I add the third task and so on.
Here is the code of the correlating part.
private void buttonSave_Click(object sender, EventArgs e)
{
if (this.textBox_Task.Text != "")
{
listView1.View = View.Details;
ListViewItem lvwItem = listView1.Items.Add(dateTimePicker1.Text);
var day = dateTimePicker1.Value.Day;
var month = dateTimePicker1.Value.Month;
var year = dateTimePicker1.Value.Year;
endTime = new DateTime(year,month,day);
//Console.WriteLine(day);
//Console.WriteLine(month);
//Console.WriteLine(year);
//Console.WriteLine(dTime
Timer t = new Timer();
t.Interval = 500;
t.Tick += new EventHandler(t_Tick);
t.Start();
lvwItem.SubItems.Add(textBox_Task.Text);
lvwItem.SubItems.Add(textBox_Note.Text);
lvwItem.SubItems.Add("");
this.dateTimePicker1.Focus();
this.textBox_Note.Focus();
this.textBox_Task.Focus();
this.textBox_Task.Clear();
this.textBox_Note.Clear();
}
else
{
MessageBox.Show("Please enter a task to add.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Information);
this.textBox_Task.Clear();
this.textBox_Note.Clear();
}
}
void t_Tick(object sender, EventArgs e)
{
TimeSpan ts = endTime.Subtract(DateTime.Now);
var hari = dateTimePicker1.Value.Day;
Console.WriteLine(ts.Days);
for (int i = 0; i < listView1.Items.Count; i++)
{
if (ts.Days == 0)
{
listView1.Items[i].SubItems[3].Text = "DEADLINE";
}
else
{
listView1.Items[i].SubItems[3].Text = ts.ToString("d' Days 'h' Hours 'm' Minutes 's' Seconds to go'");
}
}
}
It would be much appreciated for anyone who willing to help.
Thanks in advance.
Here is the link to the picture of my problem
What you are doing now is on each button click override the current endTime object by a new one like:
endTime = new DateTime(year,month,day);
If you assign a new DateTime object to endTime. You override the old one. So the first button click will work but the second will create a new object of DateTime and assign it to endTime. Next you are calculating the time difference on that one object DateTime. So it is logic that it will be the same time for each listview items
If you want to have more than one DateTime use a List to store it in like
List<DateTime> _times = new List<DateTime>();
In the button click method add the DateTime to the list
// here add the datetime to the list
DateTime dateTime = new DateTime(year, month, day);
_times.Add(dateTime);
Next you can loop thru the dates and calculate for each one the time difference in the tick method:
foreach (var dateTime in _times)
{
TimeSpan ts = dateTime.Subtract(DateTime.Now);
// etc..
}
Also you are creating a timer for each time to calculate after 500 ms. You now can use one timer this is more efficient than crating one for each time. Just assign this in the constructor
public Form1()
{
InitializeComponent();
Timer t = new Timer();
t.Interval = 500;
t.Tick += new EventHandler(t_Tick);
t.Start();
}
Whole code
public partial class Form1 : Form
{
// This is the list where the DateTimes are stored so you can have more values
List<DateTime> _times = new List<DateTime>();
public Form1()
{
InitializeComponent();
// Assign the timer here
Timer t = new Timer();
t.Interval = 500;
t.Tick += new EventHandler(t_Tick);
t.Start();
}
private void buttonSave_Click(object sender, EventArgs e)
{
if (this.textBox_Task.Text != "")
{
listView1.View = View.Details;
ListViewItem lvwItem = listView1.Items.Add(dateTimePicker1.Text);
var day = dateTimePicker1.Value.Day;
var month = dateTimePicker1.Value.Month;
var year = dateTimePicker1.Value.Year;
// Add Datetime to list
DateTime dateTime = new DateTime(year, month, day);
_times.Add(dateTime);
lvwItem.SubItems.Add(textBox_Task.Text);
lvwItem.SubItems.Add(textBox_Note.Text);
lvwItem.SubItems.Add("");
this.dateTimePicker1.Focus();
this.textBox_Note.Focus();
this.textBox_Task.Focus();
this.textBox_Task.Clear();
this.textBox_Note.Clear();
}
else
{
MessageBox.Show("Please enter a task to add.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Information);
this.textBox_Task.Clear();
this.textBox_Note.Clear();
}
}
void t_Tick(object sender, EventArgs e)
{
// loop thru all datetimes and calculate the diffrence
foreach (var dateTime in _times)
{
// Call the specific date and subtract on it
TimeSpan ts = dateTime.Subtract(DateTime.Now);
var hari = dateTimePicker1.Value.Day;
Console.WriteLine(ts.Days);
for (int i = 0; i < listView1.Items.Count; i++)
{
if (ts.Days == 0)
{
listView1.Items[i].SubItems[3].Text = "DEADLINE";
}
else
{
listView1.Items[i].SubItems[3].Text = ts.ToString("d' Days 'h' Hours 'm' Minutes 's' Seconds to go'");
}
}
}
}
}
Well, this question is related to this one, so you guys can understand it better
How to convert the "time" from DateTime into int?
My Answer to it:
txtAtiv.Text = dataGridView1.Rows[0].Cells[1].Value + "";
string value = dataGridView1.Rows[0].Cells[2].Value + "";
lblLeft.Text = value.Split(' ')[1];
textStatus.Text = "";
DateTime timeConvert;
DateTime.TryParse(value, out timeConvert);
double time;
time = timeConvert.TimeOfDay.TotalMilliseconds;
var timeSpan = TimeSpan.FromMilliseconds(time);
lblSoma.Text = timeSpan.ToString();
timer2.Start();
According to the answer I wrote right there, I want to know if there's a way I can apply it to a timer and do the DataGrid values (converted) turn into a timer value. So if I press a button they start the countdown.
I have tried to insert this code inside the timer:
private void timer2_Tick(object sender, EventArgs e)
{
string timeOp = dataGridView1.Rows[0].Cells[2].Value + "";
DateTime timeConvert;
DateTime dateTime = DateTime.Now;
DateTime.TryParse(timeOp, out timeConvert);
double time;
time = timeConvert.TimeOfDay.TotalMilliseconds;
var timeSpan = TimeSpan.FromMilliseconds(time);
if (time > 0)
{
time = time - 1000; //(millisec)
lblCountdown.text = time.ToString();
}
}
didn't count down or anything, does someone has an idea of what should I do or why it isn't working?
The value of time never changes, because you create it again fresh each time.
To solve this, you have to declare the variable you decrement outside of the Tick event.
Put these two variables on your form:
private int milliSecondsLeft = 0;
private bool timeSet = false;
Then change the 'tick' event to this:
private void timer2_Tick(object sender, EventArgs e)
{
if (!timeSet) // only get the value once
{
string dateTimeFromGrid = "4/29/2016 5:00:00 AM"; //hardcoded for simplicity, get the string from your grid
DateTime fromGrid;
DateTime.TryParse(dateTimeFromGrid, out fromGrid);
milliSecondsLeft = (int)fromGrid.TimeOfDay.TotalMilliseconds;
timeSet = true;
}
milliSecondsLeft = milliSecondsLeft - 100; // timer's default Interval is 100 milliseconds
if (milliSecondsLeft > 0)
{
var span = new TimeSpan(0, 0, 0, 0, milliSecondsLeft);
lblCountdown.Text = span.ToString(#"hh\:mm\:ss");
}
else
{
timer2.Stop();
}
}
Make sure
I have 3 columns in the ListView. From,Subject,Date
I'm using the OpenPop library.
private int numberofallmessages = 0;
private int countMsg = 0;
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
OpenPop.Pop3.Pop3Client PopClient = new OpenPop.Pop3.Pop3Client();
PopClient.Connect("mail", 110, false);
PopClient.Authenticate("me", "me",
OpenPop.Pop3.AuthenticationMethod.UsernameAndPassword);
List<string> uids = PopClient.GetMessageUids();
int messageCount = PopClient.GetMessageCount() -1;
numberofallmessages = messageCount;
allMessages = new List<OpenPop.Mime.Message>(messageCount);
for (int i = messageCount; i > 0; i--)//for (int i = messageCount - 1; i > -1; i--)
{
if (backgroundWorker1.CancellationPending == true)
{
e.Cancel = true;
return;
}
string currentUidOnServer = uids[i];
if (!seenUids.Contains(currentUidOnServer))
{
if (i > 0)
allMessages.Add(PopClient.GetMessage(i));
SaveFullMessage(PopClient.GetMessage(i), i);
w = new StreamWriter(emailsIDSFile, true);
w.WriteLine(currentUidOnServer);
w.Close();
int nProgress = (messageCount - i + 1) * 100 / messageCount;
backgroundWorker1.ReportProgress(nProgress, PopClient.GetMessageCount().ToString() + "/" + i);
}
}
PopClient.Disconnect();
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
pbt.Value = e.ProgressPercentage;
pbt.Text = e.ProgressPercentage.ToString() + "%";
pbt.Invalidate();
label8.Text = e.UserState.ToString();
label8.Visible = true;
lvnf.Items.Add(new ListViewItem(new string[]
{
allMessages[countMsg].Headers.From.ToString(), //From Column
allMessages[countMsg].Headers.Subject, //Subject Column
allMessages[countMsg].Headers.DateSent.ToString() //Date Column
}));
countMsg += 1;
}
The problem is in the progresschanged event i think. Where i add the items to each column.
When it's adding the emails to the ListView i see it like this:
The problem is on the date column the date is fine but the time in not my time. Not sure of what place the time is but in my place it's now 1:52 AM
How can i get/set the time of my place ?
I couldn't find in the line:
allMessages[countMsg].Headers.DateSent.ToString()
How to change it to my time.
Try this:
allMessages[countMsg].Headers.DateSent.ToLocalTime().ToString();
You want to utilize the DateTime.ToLocalTime() method. It does the heavy lifting for you.
Hope this helps
Edit: Removed incorrect version as the documentation for OpenPop.Net states that the MessageHeader.DateSent property is in fact a DateTime object.
I need help with timer and List.
List consist of collection of string say 5 or 6 at a time. Now, I want to display string one on label1 and it should wait for 5s and then display string 2 on label1. I have timer control and I am specifying my code in timer_tick event.
private void timer1_Tick(object sender, EventArgs e)
{
string[] myStatus = myStatusCollection.ToArray();
int length = myStatus.Length;
for (int i = 0; i < length; i++)
{
string _myStatus = myStatus[i];
//label1.ResetText();
MessageBox.Show("Twitter Status =" + _myStatus);
//label1.Text = _myStatus;
//label1.Visible = true;
}
}
I have specify, Elapse = true and interval = 5000 but still I am not able to display one string at a time. In fact, I am getting last string only. I want to rotate the strings all time.
Can anyone help me.
That's because you're looping through all the strings each time the timer event fires.
Store your index in a private variable and use that instead.
private int _index = 0;
private void timer1_Tick(object sender, EventArgs e)
{
string[] myStatus = myStatusCollection.ToArray();
string _myStatus = myStatus[_index];
//label1.ResetText();
MessageBox.Show("Twitter Status =" + _myStatus);
//label1.Text = _myStatus;
//label1.Visible = true;
if(_index == (myStatus.Length - 1))
_index = 0;
else
_index++;
}
Well it is doing just what you told it to. However, what you told it to do is not what you meant for it to do. Try this.
public class Form1 : Form {
private string[] statuses = { "A", "B", "C", "D", "E" }; // Init with proper values somewhere
private int index = 0;
private void OnTimerTick(object sender, EventArgs e) {
string status = statuses[index];
index++;
if (index == statuses.Length) { // If index = Array.Length means we're
// outside bounds of array
index = 0;
}
}
}
I'd create an int outside of the Tick to hold your position. Make sure you reset it back to 0 when you restart the process.
int MyPosition = 0;
private void timer1_Tick(object sender, EventArgs e)
{
string[] myStatus = myStatusCollection.ToArray();
int length = myStatus.Length;
if((MyPosition + 1) > length)
{
//Index Out of Range
}
else
{
string _myStatus = myStatus[MyPosition];
label1.Text = _myStatus
}
MyPosition++;
}