MyThread和Timer Control出现问题

时间:2009-10-08 20:36:12

标签: c# multithreading timer

我有一个方法,在第二个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"; 
    }

问题是,时钟已启用,但它没有滴答作响。为什么呢?

更新

正确添加Tick事件,Interval属性设置为1000。

我将Timer Control放在设计视图中的表单上。

6 个答案:

答案 0 :(得分:4)

问题是您在第二个线程上启用了计时器,并且此线程没有消息泵。

Windows窗体计时器基于SetTimer。启用计时器后,它会创建一个隐藏窗口并将该窗口的句柄发送到SetTimer API。每次计时器的间隔结束时,系统会向窗口发送WM_TIMER消息。隐藏窗口然后处理该消息并引发Tick事件。

在您的情况下,计时器是在第二个线程上创建的,但它没有消息泵,因此WM_TIMER消息永远不会到达您的窗口。您要做的是在UI线程上启用计时器,以便在发送WM_TIMER消息时,在具有消息泵的UI线程中处理它。假设您的程序在表单类中,您可以使用 this 对表单的引用来编组调用以启用计时器(如果它不在表单类中,您需要引用该表单形式)如此:

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
}

答案 1 :(得分:3)

在启动计时器之前,您需要将其Tick事件附加到您要处理事件的方法。在这种情况下,您可以在启动计时器之前执行此操作:

clock.Tick += this.clock_Tick;

答案 2 :(得分:1)

只有主线程才能更新UI。假设您的时钟已正确初始化(正如其他人指出的那样)并且正在从第二个线程调用“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";
    }
}

这适用于WinForms .. WPF语法略有不同,但功能相同。

以下是关于整个事件的文章:http://weblogs.asp.net/justin_rogers/pages/126345.aspx

祝你好运!

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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