リストを列挙するか、C#でタイマーまたはディスパッチャーでx秒ごとにdictを実行する

私は3つの値/キーのペアを持つ辞書を持っていると言う。

private void someMethod()
{
    Dictionary d = new Dictionary();
    d.Add("cat", 22);
    d.Add("dog", 14);
    d.Add("llama", 2);
    d.Add("iguana", 6);

    somesortoftimercode
}

private void DisplayText(string x, int y)
{
    label1.Text = x;
    int someValue= 3+y;
}

私はこの辞書を通して繰り返したい、私は3秒ごとにディクショナリ値でdisplayTextを呼び出すdispatchertimer(またはタイマー)します。それ、どうやったら出来るの?

更新:

私はThread.Sleep(XXX)を使用することはできません、私はスレッドをブロックすることはできません。私はバックグラウンドで別のものを持っている、と私は場所のすべてのスレッドを持ってこれを回すことはできません。

plus: http://msmvps.com/blogs/peterritchie/archive/2007/04/26/thread-sleep-is-a-sign-of-a-poorly-designed-program.aspx

0
どのバージョンのC#を使用していますか?
追加された 著者 Miguel Angelo,

5 答え

private Timer timer;

private void someMethod()
{
    var d = new Dictionary
                {
                    {"cat", 22}, 
                    {"dog", 14}, 
                    {"llama", 2}, 
                    {"iguana", 6}
                };

    int index = 0;
    TimerCallback timerCallBack = state =>
                                        {
                                            DisplayText(d.ElementAt(index).Key, d.ElementAt(index).Value);
                                            if(++index == d.Count)
                                            {
                                                index = 0;
                                            }
                                        };
    timer = new Timer(timerCallBack, null, TimeSpan.Zero, TimeSpan.FromSeconds(3));
}

private void DisplayText(string x, int y)
{
    label1.Text = x;
    int someValue= 3+y;
}

列挙型辞書が一度だけ必要な場合は、次のコードを使用できます。

new Task(() =>
    {
        d.All(kvp =>
        {
            DisplayText(kvp.Key, kvp.Value);
            Thread.Sleep(3000);
            return true;
        });
    }
).Start();
2
追加された
いいえ、thread.sleepは使用できません。スレッドをブロックできません。
追加された 著者 darthwillard,
メイン以外のスレッドをブロックすることができます。私は答えを更新しました。
追加された 著者 Yuriy Rozhovetskiy,

フレームワークが提供するタイマーのいずれかを使用することができます。

System.Threading.Timers.Timer

インターバルを任意の値に設定し、Tickイベントコールで、あなたのコレクションを反復する foreach ループを設定します。あなたの例に従って

foreach(var pair in d)
{ 
   DisplayText(pair.key, pair.value);
}
1
追加された
これは私のためには機能しません。 foreachループは、指定された時刻に1つずつではなく、すべての1つを一度に処理します。
追加された 著者 darthwillard,
foreach(var kvp in d){DisplayText(kvp.Key、kvp.Value);}を実行すると、数ミリ秒節約できます。 } を使用して、毎回値を参照しないようにします。
追加された 著者 Joe Enos,
@ JoeEnosと私の答えを変更する、キーの複数の値がある場合、実際にはより正確です。
追加された 著者 msarchet,

Microsoft Cloud Teamのリアクティブエクステンション(Rx)は、あなたが望むことをやるのにとても良い方法があります。

Rxへの参照を(NuGet経由で)追加したら、これをあなたの someMethod メソッドにドロップするだけです:

Observable
    .Interval(TimeSpan.FromSeconds(3.0))
    .ObserveOnDispatcher()
    .Subscribe(x =>
    {
        d.ToArray()//Helps to prevent race conditions
            .ForEach(kvp => DisplayText(kvp.Key, kvp.Value));
    });

バックグラウンドスレッドで起動するタイマーを設定し、スレッド間の問題を防ぐためにディスパッチャ(UIスレッド)への呼び出しをマーシャリングします。

Windows Formsを使用している場合、 .ObserveOnDispatcher() .ObserveOn(label1)または。ObserveOn(form)行ってもいい。

スレッド、タイマー、またはバックグラウンドワーカーを明示的に作成する必要はありません。

Rxのリンクは次のとおりです。

0
追加された

labell という名前のラベルを含むフォームを作成し、このコードを試してください:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        someMethod();
    }

    Thread thread;
    private void someMethod()
    {
        Dictionary d = new Dictionary();
        d.Add("cat", 22);
        d.Add("dog", 14);
        d.Add("llama", 2);
        d.Add("iguana", 6);

        thread = new Thread(new ParameterizedThreadStart(Do));
        thread.Start(d);
    }

    delegate void _DisplayText(string x, int y);
    private void DisplayText(string x, int y)
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new _DisplayText(DisplayText), x, y);
            return;
        }
        label1.Text = x;
        int someValue = 3 + y;
    }

    public void Do(object dic)
    {
        Dictionary d = (Dictionary)dic;
        while (true)
        {
            foreach (var item in d)
            {
                DisplayText(item.Key, item.Value);
                Thread.Sleep(3000);
            }
        }
    }
}
0
追加された
いいえ、これはthread.sleepで行うことはできません。待っている間にブロックすることはできません
追加された 著者 darthwillard,
私は別のスレッドを作成したので、待機中にブロックされないことに注意してください。
追加された 著者 Miguel Angelo,
このサンプルコードを試してみると、プログラムのGUIとやりとりできますが、別のスレッドで3秒ごとにラベルが変わることがわかります。
追加された 著者 Miguel Angelo,

これはあなたが正しい方向に進むようにするはずです。私はあなたがWinフォームアプリケーションを作成していると仮定します。そうでない場合、これはあなたのためには機能しません。

    private System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
    private Dictionary d = new Dictionary()
    {
        {"cat", 22},
        {"dog", 14},
        {"llama", 2},
        {"iguana", 6}
    };
    public Form1()
    {
        InitializeComponent();
        t.Tick += new EventHandler(t_Tick);
        t.Start();
    }

    void t_Tick(object sender, EventArgs e)
    {
        t.Stop();
        foreach (var item in d)
        {
            label1.Text = item.Key;
            int someValue = 3 + item.Value;
        }
        t.Start();
    }
0
追加された