opsommen via een lijst of dicteren elke x seconden met timer of dispatchertimer in C #

stel dat ik een woordenboek heb met 3 waarde/sleutelparen.

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;
}

ik wil iterate door dit woordenboek, ik wil dat een dispatchertimer (of timer) displayText met de woordenboekwaarden elke 3 seconden oproept. hoe doe ik dat?

BIJWERKEN:

ik kan Thread.Sleep (XXX) niet gebruiken, ik kan de draad niet blokkeren. ik heb andere dingen die op de achtergrond gaan, en ik kan dit niet uitdraaien om overal discussies te hebben.

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

0
Welke versie van C# gebruikt u?
toegevoegd de auteur Miguel Angelo, de bron

5 antwoord

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;
}

Als u alleen een opsomming van het woordenboek nodig heeft, kunt u de volgende code gebruiken:

new Task(() =>
    {
        d.All(kvp =>
        {
            DisplayText(kvp.Key, kvp.Value);
            Thread.Sleep(3000);
            return true;
        });
    }
).Start();
2
toegevoegd
nee, kan thread.sleep niet gebruiken. kan de draad niet blokkeren.
toegevoegd de auteur darthwillard, de bron
Je kunt een andere thread blokkeren, niet de main. Ik heb update-antwoord.
toegevoegd de auteur Yuriy Rozhovetskiy, de bron

U kunt elk van de timers gebruiken die door het framework worden geboden, zoals

System.Threading.Timers.Timer

Stel het interval in op wat u maar wilt en bel vervolgens in de gebeurtenis Tick een foreach lus die itereert over uw verzameling. Volgens jouw voorbeeld

foreach(var pair in d)
{ 
   DisplayText(pair.key, pair.value);
}
1
toegevoegd
niet, dit werkt niet voor mij. de foreach-lus zal elke single tegelijk passeren, niet één op een bepaald tijdstip.
toegevoegd de auteur darthwillard, de bron
U kunt een paar milliseconden opslaan door foreach te doen (var kvp in d) {DisplayText (kvp.Key, kvp.Value); } , om te voorkomen dat u elke keer de waarden opzoekt.
toegevoegd de auteur Joe Enos, de bron
@ JoeEnos en het is eigenlijk meer correct als er meerdere waarden zijn voor een sleutel, waardoor ik mijn antwoord verander.
toegevoegd de auteur msarchet, de bron

De Reactive Extensions (Rx) (van het Microsoft Cloud Team) heeft een hele leuke manier om te doen wat je wilt.

Na het toevoegen van verwijzingen naar Rx (wat je kunt doen via NuGet), kun je dit gewoon in je someMethod -methode plaatsen:

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

Het installeert de timer - die op een achtergrondthread wordt geactiveerd - en ordt vervolgens de aanroep naar de dispatcher (dat wil zeggen, UI-thread) om problemen met threads te voorkomen.

Als u Windows Forms gebruikt, wordt de .ObserveOnDispatcher() .ObserveOn (label1) of .ObserveOn (formulier) en u bent klaar om te vertrekken.

Je hoeft je niet druk te maken over het expliciet maken van threads, timers of achtergrondmedewerkers.

Dit zijn de links voor Rx:

0
toegevoegd

Maak een formulier met een label met de naam labell en probeer deze code:

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
toegevoegd
nee, dit kan niet gedaan worden met thread.sleep. ik kan het niet laten blokkeren terwijl het wacht
toegevoegd de auteur darthwillard, de bron
Merk op dat het niet blokkeert terwijl het wacht, omdat ik een nieuwe thread heb gemaakt.
toegevoegd de auteur Miguel Angelo, de bron
Als u deze voorbeeldcode probeert, ziet u dat u nog steeds de GUI van het programma kunt gebruiken, terwijl een andere thread ervoor zorgt dat het label om de 3 seconden wordt gewijzigd.
toegevoegd de auteur Miguel Angelo, de bron

Dit zou je in de goede richting moeten laten gaan. Ik neem aan dat je een Win Forms-applicatie maakt. Zo niet, dan werkt dit niet voor u.

    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
toegevoegd