简体   繁体   English

MyThread和Timer控件出现问题

[英]A problem with MyThread and the Timer Control

I have a 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)
    {
        //show how many bytes we have read in each second
        this.label6.Text = ByteCount.ToString() + " B/s"; 
    }

the problem is, the clock is Enabled, but it's not ticking. 问题是时钟已启用,但没有滴答作响。 Why? 为什么?

Updates: 更新:

The Tick event is properly added, the Interval property is set to 1000. Tick事件已正确添加,Interval属性设置为1000。

I put the Timer Control on the form in the Design View. 我将计时器控件放在设计视图中的窗体上。

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. Windows窗体计时器基于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. 启用计时器后,它将创建一个隐藏的窗口,并将该窗口的句柄发送到SetTimer API。系统又会在每次计时器间隔过去时向该窗口发送WM_TIMER消息。 The hidden window then processes that message and raises the Tick event. 然后,隐藏的窗口处理该消息并引发Tick事件。

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. 在您的情况下,计时器是在第二个线程上创建的,但是它没有消息泵,因此WM_TIMER消息永远不会到达您的窗口。 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. 您要做的是在UI线程上启用计时器,以便在发送WM_TIMER消息时在具有消息泵的UI线程中对其进行处理。 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
}

Before you start the timer you need to attach its Tick event to your method that you want to handle the event. 在启动计时器之前,您需要将其Tick事件附加到要处理该事件的方法上。 In this case you would do this prior to starting the timer: 在这种情况下,您可以在启动计时器之前执行以下操作:

clock.Tick += this.clock_Tick;

Only the main thread can update the UI. 只有主线程可以更新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: 假设您的时钟已正确初始化(正如其他人指出的那样),并且正在从第二个线程调用“ clock_Tick”,则需要这样重写它:

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. WPF语法略有不同,但在功能上是相同的。

Here's an article on the whole affair: http://weblogs.asp.net/justin_rogers/pages/126345.aspx 这是有关整个事件的文章: http : //weblogs.asp.net/justin_rogers/pages/126345.aspx

Good luck! 祝好运!

您是否设置了时钟的Interval属性?

这只是一个猜测,但是请确保您的计时器控件的Tick事件已正确绑定到您的clock_Tick方法。

您可能遇到“ System.timer”和“ windows.form.timer”冲突,System.timer在单独的线程上运行,而form.timer在主线程中运行,以便在.designer.cs中更改“计时器”到“ System.windows.form.timer”,它应该可以正常工作

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM