2009-10-08 53 views
3

我有一個方法,這是在第二個線程被調用的一個問題:與MyThread的和定時器控制

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。

我把定時器控制在設計視圖的形式。

+0

你如何初始化時鐘? – M4N 2009-10-08 20:42:03

+0

我剛剛在設計視圖中的窗體中放置了定時器控件 – Tony 2011-02-23 15:48:54

+0

正確添加了Tick事件,Interval屬性設置爲1000 – Tony 2011-02-23 15:49:08

回答

4

的問題是,你使您的第二個線程的計時器,這線程沒有消息泵。

的Windows窗體計時器是基於SetTimer的。當定時器被啓用時,它會創建一個隱藏窗口,並將該窗口的句柄發送到SetTimer API,系統每次定時器的時間間隔結束後都會向窗口發送WM_TIMER消息。然後隱藏窗口處理該消息並引發Tick事件。

在您的情況計時器在第二個線程上創建的,但它沒有一個消息泵所以WM_TIMER消息永遠不會到達你的窗口。你想要做的就是在你的UI線程上啓用計時器,這樣當發送WM_TIMER消息時,它將在具有消息泵的UI線程中處理。假設你的程序是你的表單類中,你可以使用這個參考到您的表單當元帥的呼叫,能定時器(如果不是窗體類中,您需要形式的引用),如下所示:

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 
} 
+0

+1我從來沒有想過在這個問題上使用Invoke。謝謝@Stephen Martin。 – mammadalius 2012-02-15 13:39:26

0

您是否設置了時鐘的Interval屬性?

3

開始之前,你需要將其Tick事件附加到要處理事件的方法定時器。在這種情況下,你會做啓動定時器在此之前:

clock.Tick += this.clock_Tick; 
0

這只是一個猜測,但要確保你的計時器控件的Tick事件正確綁定到你的clock_Tick方法。

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

祝你好運!

0

您可能會有一個「System.timer」和一個「windows.form.timer」衝突,System.timer在單獨的線程上運行,而form.timer在主線程中運行以便在.designer中運行。 CS改變「計時器」到「System.windows.form.timer」它應該工作,那麼