San
San

Reputation: 1837

Windows Timer in a TextBox

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

Answers (3)

etaiso
etaiso

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

Brian A. Henning
Brian A. Henning

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

Sinatr
Sinatr

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

Related Questions