Reputation: 1837
I am trying check if it is possible to show timer in a Textbox on click of a button. on button click the timer should start running and after the process is done I want to stop the timer. Below is what I have. What should I chnage to make it work?
public partial class MyClass: Form
{
public MyClass()
{
InitializeComponent();
InitializeTimer();
}
private void InitializeTimer()
{
this.timer1.Interval = 1000;
this.timer1.Tick += new EventHandler(timer1_Tick);
// don't start timer until user clicks Start
}
private void timer1_Tick(object sender, EventArgs e)
{
processingMessageTextBox.Invoke(new MethodInvoker(delegate { processingMessageTextBox.Text = "show running time after click"; }));
}
private void myButton_Click(object sender, EventArgs e)
{
this.timer1.Start();
doSomeTimeCOnsumingWork();
this.timer1.Stop();
}
}
Please suggest.
Upvotes: 1
Views: 2308
Reputation: 2746
I would use another Thread
(or BackgroundWorker
) for updating the TextBox
(or Label
) with the elapsed time, until work is done.
And I would also use Stopwatch
instead of Timer
(easier to get the elapsed time).
Code as follows;
First, add this field:
private Stopwatch sw = new Stopwatch();
Now, add a BackgroundWorker
to update the time.
In the BackgroundWorker
DoWork
event, have this code, to keep update the appropriate TextBox
or Label
with the elapsed time:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
while (sw.IsRunning)
{
// Display elapsed time in seconds.
processingMessageTextBox.Invoke(new MethodInvoker(delegate { processingMessageTextBox.Text = (sw.ElapsedMilliseconds / 1000).ToString(); }));
}
}
Make sure that your doSomeTimeCOnsumingWork
is running on another thread, so you won't block the UI.
You could use another BackgroundWorker
for this purpose or just use Thread
class.
In your doSomeTimeCOnsumingWork
(you can create another BackgroundWorker for it) add the following:
private void doSomeTimeCOnsumingWork()
{
sw.Reset();
sw.Start();
// Some work done here
sw.Stop();
}
Upvotes: 1
Reputation: 1511
Your call to doSomeTimeConsumingWork()
happens on the GUI thread. Windows Forms is single-threaded--what this means is that the timer will not be serviced until doSomeTimeConsumingWork()
returns. Furthermore, as another answer mentions, there's no need to use Invoke
with a Windows Forms Timer, as it is already on the GUI thread.
Investigate the System.Windows.Forms.BackgroundWorker
class to put your time-consuming work on a separate thread. BackgroundWorker
includes a mechanism for reporting progress. See this MSDN article.
Upvotes: 1
Reputation: 22052
There are dozen of errors methink.
MyClass
is not the right name for the form.
No need to Invoke
in the timer event (as its created in UI thread), simply do event
private void timer1_Tick(object sender, EventArgs e)
{
processingMessageLabel.Text = "show running time after click";
}
myButton_Click
event performs all the job at once, blocking UI thread, make it more like this (to toggle timer1
)
private void myButton_Click(object sender, EventArgs e)
{
timer1.Enabled = !timer1.Enabled;
}
What else? You want to perform doSomeTimeConsumingWork
? Why don't you use Thread
, Task
or BackgroundWorker
for this?
Upvotes: 1