2012-01-13 6 views
0

2秒ごとにリストボックスの選択インデックスのインデックスを変更したいと思います。スレッドボックスを使用して2秒ごとにlistBoxの選択されたインデックスを変更します

public Form1() 
{ 
    InitializeComponent(); 
    listBox1.Items.Add("A"); 
    listBox1.Items.Add("B"); 
    listBox1.Items.Add("C"); 
    listBox1.Items.Add("D"); 
    listBox1.Items.Add("E"); 
    listBox1.Items.Add("F"); 
} 

public void SelectEvery2Sec() 
{ 
    System.Windows.Forms.Timer timer=new System.Windows.Forms.Timer(); 
    for (int i = 0; i < listBox1.Items.Count; i++) 
    { 
     timer.Start(); 
     listBox1.SelectedIndex = i; 
     try 
     { 
      Thread.Sleep(2000); 
     } 
     catch{} 

     if(i == listBox1.Items.Count -1) 
      i = 0; 
    } 
} 

しかし、私たちはメインスレッドを停止できません。アプリケーションが実行されますが、GUIが表示されませんでした。それは正しい方法ではないので、私は次の方法、すなわち別のスレッドを試しています。

新しいスレッドを作成しますが、スレッドのクロスアクセスは許可されていませんか?

答えて

1

次に、新しいスレッドを作成しますが、スレッドのクロスアクセスは許可されていませんか?

正しい。 UI以外のスレッドからUIコントロールにアクセスすることはできません。試してみると例外が発生します。

複数のスレッドが必ずしもすべての場合に適切なソリューションであるとは限りません。このような状況では、タイマーコントロールが簡単になります。希望するタイプコントロールはSystem.Windows.Forms.Timerです。

また、BackgroundWorker componentを使用することもできます。あなたがしなければならないことは、設計時にあなたのフォームにそれを追加することだけです。それはあなたのためにすべての汚い作業を処理します。 MSDNのページには素晴らしいサンプルがあります。

注:Thread.Sleep is the sign of a poorly-designed programに注意してください。あなたが自分のコードに書いていることが分かったら、それは間違っています。ほぼ確実に良い方法があります。

このタイプの質問はStack Overflowで非常に多くの質問をします。検索を実行すると詳細が表示されます。

0

タイマーオブジェクトのIntervalを2000ミリ秒に設定します。メインスレッドをスリープ状態にしないでください。

Timer Elapsedイベントを処理し、コントロールを更新できます。

UPDATE:

二つのスレッドでそれを作るために、すべての2000ミリとワイヤーあなたのメソッドがそれには第2のスレッドでイベントを発生させます。このメソッドでは、フォームのコントロールを変更できます。

+0

になります。明示的に2つのスレッドが必要です。 –

0

System.Windows.Forms.Timerの代わりにSystem.Threading.Timerを使用してください。これは、ワーカースレッドで実行できます。

タイマタイムアウトイベントハンドラは、 ListBox.SelectedItemを変更ヨーヨーが Invokeにそれを必要とするウメイとしてのListBox選択した項目を変更するに Invoke.Requiredを必ず確認して関数を呼び出してもらいます。

+0

非UIスレッドからUIコントロールと対話するには、必ず 'Invoke'(または' BeginInvoke')を使う必要があります。しかし、あなたが 'BackgroundWorker'を使ってそれをすべて扱うだけで、すべての接着剤を一緒にまとめることは無意味です。 –

1

TimerまたはBackgroundWorkerを使用してこれを行うことができます。 Timerの場合は、Intervalを2秒に設定します。 BackgroundWorkerの場合はRunWorkerAsyncを使用してください。

cross thread access issue使用する場合

public static class ControlExtensions 
{ 
    public static void Invoke(this Control control, Action action) 
    { 
     if (control.InvokeRequired) control.Invoke(new MethodInvoker(action), null); 
     else action.Invoke(); 
    } 
} 

あなたの古いコード

listBox1.SelectedIndex = i; 

は、私はタイマーを使用したくない

listBox1.Invoke(() => { listBox1.SelectedIndex = i; }); 
+1

'Timer'を使用する場合は' Invoke'する必要はありません。それは一種のポイントです。タイマーはUIスレッドでイベントを発生させます。これは必要なものです。 –

+0

あなたのポイントを得ました。ありがとう。 –

関連する問題