2017-05-26 22 views
0

我最近開始學習C#,我試圖在計時器的幫助下每分鐘重複一次方法。該方法更改標籤的值。但是,我收到以下錯誤:C# - Winforms - 重複定時器的幫助下的方法

$exception {"Cross-thread operation not valid: Control 'label1' accessed from a thread other than the thread it was created on."} System.Exception {System.InvalidOperationException}

我試過尋找解決方案,每個線程都讓我困惑。我不只需要正確的代碼,還需要解釋,因爲我想學習使用定時器和線程來操作UI。

下面是我的代碼:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Timers; 
using System.Windows.Forms; 



namespace Winforms_Timer_and_Thread 
{ 
    public partial class Form1 : Form 
    { 

     System.Timers.Timer myTimer = new System.Timers.Timer(); 
     public Form1() 
     { 
      myTimer.Enabled = true; 
      InitializeComponent(); 
     } 

     public void startMethod(object senter, ElapsedEventArgs e) 
     { 
      int cntr = 0; 
      cntr++; 
      label1.Text = "Executed: " + cntr.ToString(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      label1.Text = "Started!"; 
      myTimer.Enabled = true; 
      myTimer.Interval=(1*60*1000); 
      myTimer.Elapsed += new System.Timers.ElapsedEventHandler(startMethod); 

     } 

    } 
} 
+0

看到的是https:// stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c 您無法直接從非ui線程訪問用戶界面。 –

+2

你也可以考慮改用System.Windows.Forms.Timer。 –

+0

@James R.但是那麼可以每分鐘調用一次該方法嗎? – Tango

回答

2

如果更改使用System.Windows.Forms.Timer,你不會有這樣的問題,因爲它在相同的UI線程的執行。

你只需要改變:

  • 類型從System.Timers.Timer計時器來System.Windows.Forms.Timer
  • 是被訂閱的事件從ElapsedTick
  • 事件簽名,其中ElapsedEventArgs e成爲EventArgs e

您還只需要訂閱活動一次,並非每次啓用計時器時,都應將其移至事件,並將Interval賦值(儘管可隨時更改)。

您可能還需要存儲StartMethod外的計數器變量,所以它會在每次執行時增加,然後重置每次到零啓動計時器:

public partial class Form1 : Form 
{ 
    readonly System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer(); 
    private int tickCounter; 

    public Form1() 
    { 
     InitializeComponent(); 

     myTimer.Interval = (int)TimeSpan.FromMinutes(1).TotalMilliseconds; 
     myTimer.Tick += StartMethod; 
    } 

    private void StartMethod(object sender, EventArgs e) 
    { 
     tickCounter++; 
     label1.Text = "Number of executions: " + tickCounter; 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     tickCounter = 0; 
     label1.Text = "Started!"; 
     myTimer.Enabled = true; 
    } 
}