2012-03-02 2 views
2

私はタイマーとスレッドが新しく、MainWindowのコントロールを編集/変更する関数を呼び出すタイマーの作成方法がわかりません。System.Timers.Timerを使用して別のスレッドのコントロールにアクセス/変更する方法?

XAMLコード:

<Window x:Class="TimerTest.MainWindow" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Title="MainWindow" Height="350" Width="525"> 
<Grid> 
<TextBox Height="287" HorizontalAlignment="Left" Margin="12,12,0,0" Name="textBox1" VerticalAlignment="Top" Width="479" /> 
</Grid> 
</Window> 

C#コード:

namespace TimerTest 
{ 
    public partial class MainWindow : Window 
    { 
     //Declaring my aTimer as global 
     public static System.Timers.Timer aTimer; 
     //Function that is called 
     public void OnTimedEvent(object source, ElapsedEventArgs e) 
     { 
      textBox1.Text += "SomeText "; 
     } 
     public MainWindow() 
     { 
      InitializeComponent(); 
      aTimer = new Timer(); 
      aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent); 
      aTimer.Interval = 1000; // every 5 seconds 
      aTimer.Enabled = true; 
     } 
    } 
} 

私が取得エラー: "別のスレッドがそれを所有しているので、呼び出し元のスレッドがこのオブジェクトにアクセスすることはできません。" P .:私は代議員とはあまりよくないので、この場合私が助けてくれると思うなら、コードサンプルを投稿してください。

+0

:http://stackoverflow.com/questions/4115598/controls-and-threads/4115634#4115634 – davisoa

+0

なぜこのスレッドタイマークラスを使用して、System.Windows.Forms.Timerがある場合にビジュアルコントロールにアクセスするのですか? –

+0

@davisoa:Bleah、再帰的更新メソッドを使用するコードスニペットは嫌です。何が起こっているのかを理解するのに、私には常に5分かかります。 – Tudor

答えて

9

aTimer.SynchronizingObject = this; 

タイマーを作成した後、あなたがdelegateの内側に、あなたの更新コードをラップし、textBox1.Dispatcher.BeginInvokeにそれを渡す必要があります別のスレッドからのコントロールを変更するには

、またはToolBox-> Components(System.Windows.Forms.Timer)からタイマーのOTHER型を使用します。

現在使用しているタイマーは、UIプールではなくスレッドプールスレッドで発生しますので、UIスレッドと同期して必要な方法で作業する必要があります。

+0

私はまだC#と.NETのnoobieだから、これは最も簡単な答えだから、aTimer.SyncronizingObject = this; did not work:[(キャストに関する構文が間違っていますが)System.Windows.FormsのTimerが魅力的に機能しました:]ありがとう! –

4

特定のコントロールに関連付けられたスレッドのみが、そのコントロールを変更できます。ただ、追加

namespace TimerTest 
{ 
    public partial class MainWindow : Window 
    { 
     private delegate void updateDelegate(string text); 

     private void updateTextBox(string text) 
     { 
      textBox1.Text += text; 
     } 

     //Declaring my aTimer as global 
     public static System.Timers.Timer aTimer; 
     //Function that is called 
     public void OnTimedEvent(object source, ElapsedEventArgs e) 
     { 
      textBox1.Dispatcher.BeginInvoke(
        new updateDelegate(updateTextBox), "SomeText "); 
     } 
     public MainWindow() 
     { 
      InitializeComponent(); 
      aTimer = new Timer(); 
      aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent); 
      aTimer.Interval = 1000; // every 5 seconds 
      aTimer.Enabled = true; 
     } 
    } 
} 
+0

有用な情報ありがとうございますが、私はまだ代議員を使用することに恥ずかしがりますので、System.Windows.Formsのタイマーを使用していますが、次回もこのことを覚えておいていただきたいと思います。 –

+0

updateDelegateは次のように定義する必要があります: 'private ** delegate ** void updateDelegate(文字列テキスト);' – matuuar

+0

@matuuar:ありがとうございます。 – Tudor

1

問題は、別のスレッドからUIスレッドを更新しようとしていることです。 WinFormsでは、コールをUIスレッドにマーシャリングする必要があります。 WPF .NET Best way to trigger an event every minuteからの例に続いて

、WPFにあなたがディスパッチャタイマーを使用することができます。

と同様に
public static System.Windows.Threading.DispatcherTimer aTimer; 


    public WindowUpdatedByTimer() 
    { 
     InitializeComponent(); 

     aTimer = new System.Windows.Threading.DispatcherTimer(); 
     aTimer.Tick += new EventHandler(OnTimedEvent); 
     aTimer.Interval = TimeSpan.FromSeconds(5); 
     aTimer.Start(); 

    } 

    public void OnTimedEvent(object source, EventArgs e) 
    { 
     textBox1.Text += "SomeText "; 
    } 
+0

すばやく便利な返信をありがとう! :] System.Windows.Forms.Timerによく似ていますが、スレッドについてはあまり分かりませんので、現時点ではほぼ同じです:/神にはxDを学ぶことがたくさんあります –

+0

問題ありません。 WindowsタイマーはWpfではなくWinFormsのターゲットになっていることに注意してください。それはそれを使用してあなたを停止するではありません。スレッド化は大きな話題ですが、一般的にはC#に満足すれば取り組むだけの価値があります。あなたのUIのための1つのスレッドがありますので、あなたはそれをユーザーのために敏感に保つ必要があります。関心がある場合は、http://msdn.microsoft.com/en-us/library/ms173178.aspxを参照してください。 – kaj

関連する問題