views:

234

answers:

8

Hi, I have e.g that method, which is being invoked in the second Thread:

    public byte[] ReadAllBytesFromStream(Stream input)
    {
        clock.Start();

        using (...)
        {
            while (some conditions) //here we read all bytes from a stream (FTP)
            {
                ...
 (int-->)       ByteCount = aValue;
                ...
             }
            return .... ;
        }
    }

    private void clock_Tick(object sender, EventArgs e)
    {
        this.label6.Text = ByteCount.ToString() + " B/s"; //show how many bytes we have read in each second
    }

the problem is, the clock is Enabled, but it's not ticking. Why ?

A: 

I have just put the Timer Control on the form in the Design View

Tony
A: 

Did you set the Interval property of the clock?

M4N
+3  A: 

Before you start the timer you need to attach its Tick event to your method that you want to handle the event. In this case you would do this prior to starting the timer:

clock.Tick += this.clock_Tick;
Andrew Hare
A: 

this is just a guess, but make sure that your timer control's Tick event is correctly bound to your clock_Tick method.

Michael Abdelmalek
A: 

The Tick event is properly added, the Interval property is set to 1000

Tony
+1  A: 

Only the main thread can update the UI. Assuming you have your clock initialized correctly (as others have pointed out) and that "clock_Tick" is being invoked from your 2nd thread, you need to rewrite it like this:

private void clock_Tick(object sender, EventArgs e)
{
    // InvokeRequired will be true on every thread EXCEPT the UI thread
    if (label6.InvokeRequired)
    {
        // Issue an asynchoronous request to the UI thread to perform the update
        label6.BeginInvoke(new MethodInvoker(this.clock_Tick), sender, e);
    }
    else
    {
        // Actually do the update
        label6.Text = ByteCount.ToString() + " B/s";
    }
}

That's for WinForms.. the WPF syntax is slightly different, but functionally the same.

Here's an article on the whole affair: http://weblogs.asp.net/justin%5Frogers/pages/126345.aspx

Good luck!

Andy S
A: 

You May have a "System.timer" and a "windows.form.timer" conflict the System.timer runs on a separate thread while the form.timer runs in the main thread in order to in the .designer.cs change the "timer" to "System.windows.form.timer" it should then work

micalexlea
+1  A: 

The problem is that you are enabling your timer on the second thread and this thread does not have a message pump.

The Windows forms timer is based on SetTimer. When the timer is enabled it creates a hidden window and sends the handle to that window to the SetTimer API, The system, in turn, sends the window a WM_TIMER message every time the interval for the timer has elapsed. The hidden window then processes that message and raises the Tick event.

In your situation the timer is created on the second thread but it does not have a message pump so the WM_TIMER message never reaches your window. What you want to do is enable your timer on your UI thread so that when the WM_TIMER message is sent it is processed in the UI thread which has a message pump. Assuming your procedure is inside your form class you can use the this reference to your form to marshal the call to enable the timer (if it isn't inside the form class you'll need a reference to the form) like so:

public byte[] ReadAllBytesFromStream(Stream input)
{
    if(this.InvokeRequired)
    {
        this.Invoke(new MethodInvoker(clock.Start));
    }
    else
    {
        clock.Start();
    }

    using (...)
    {
        while (some conditions) //here we read all bytes from a stream (FTP)
        {
            ...
 (int-->)   ByteCount = aValue;
            ...
         }
        return .... ;
    }
}

private void clock_Tick(object sender, EventArgs e)
{
    this.label6.Text = ByteCount.ToString() + " B/s"; //show how many bytes we have read in each second
}
Stephen Martin