需要一个在列表框中的每个完成项目后更新的计时器

时间:2011-03-02 07:28:14

标签: c# winforms

现在我已经实现了这样的计时器类。

    static void DelaySec(string delayName)
    {
        switch (delayName)
        {
            case "Delay1":
                System.Threading.Thread.Sleep(1000);
                break;
            case "Delay2":
                System.Threading.Thread.Sleep(2000);
                break;
            case "Delay3":
                System.Threading.Thread.Sleep(3000);
                break;
            case "Delay4":
                System.Threading.Thread.Sleep(4000);
                break;
            case "Delay5":
                System.Threading.Thread.Sleep(5000); 
                break;
            default:
                break;
        }
    }

我想在列表框中的项目之间设置延迟而不是睡眠,因此我的UI不会冻结。

希望有人可以帮助我。

3 个答案:

答案 0 :(得分:3)

如果你正在做大量的工作 - 甚至模拟它 - 你应该在UI线程上做这件事。这就是你的UI线程冻结的原因。

您应该在后台线程上执行此操作,并使用Control.Invoke / BeginInvoke或可能BackgroundWorker将任何UI更新(例如更改进度条)封送回UI线程

目前还不清楚你的计时器在这里做了什么,但是当你找到如何将工作卸载到另一个线程时,然后描述你的代码是什么样的。

请注意,您可以使用System.Windows.Forms.Timer轻松地与UI线程进行交互 - 但它仍然应该基于事件,而不是在UI线程中运行大量工作。因此,例如,您可以创建要执行的工作“队列”(基于列表框项目),设置计时器以每秒触发,并在每个计时器上执行工作 - 如果它很短 - 为该项目。在调用之间,UI线程可以自由更新。

请注意,C#5的异步功能意味着能够像这样编写正常的顺序代码,但这还有一段距离。

答案 1 :(得分:0)

    ...
    stopwatch.Start();
    timerLabel.Visible = true;
    progressBar1.Maximum = SequenceListBox.Items.Count;
    progressBar1.Step = (progressBar1.Maximum / SequenceListBox.Items.Count);
    progressBar1.PerformStep();
    foreach(ElementControl item in SequenceListBox.Items)
    {
        item.RunElement();
        Application.DoEvents();
    }
    stopwatch.Stop();
    ...

答案 2 :(得分:0)

我认为这是你想要实现的目标。但是,我不确定当秒表开始和停止计时。您的示例似乎是多次启动手表并且只停止一次。

    private int currItem;
    private List<ElementControl> Elements = new List<ElementControl>();
    private void StartButton_Click(object sender, EventArgs e)
    {            
        if (SequenceListBox.Items.Count <= 0)
        {
            MessageBox.Show("Please select an Item");
            return;
        }

        // Prevent starting again
        StartButton.Enabled = false;

        Elements.Clear();
        foreach (ElementControl ele in SequenceListBox.Items)
            Elements.Add(ele);

        // Must start stopwatch before timer to prevent timer_Elapsed from closing a non-existent stopwatch
        stopwatch = Stopwatch.StartNew();
        stopwatch.Start();

        // Start timer
        System.Timers.Timer timer = new System.Timers.Timer(1000);
        timer.AutoReset = true;
        timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
        timer.Start();
    }

    public delegate void ReportProgressHandler(int value, string text);
    private void ReportProgress(int value, string text)
    {
        if (InvokeRequired)
            Invoke(new ReportProgressHandler(ReportProgress), value, text);
        else
        {
            if(value <= progressBar1.Maximum)
                progressBar1.Value = value;
            timerLabel.Text = text;
        }
    }
    private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        // If all item process, stop timer, stopwatch and re-enable button
        if (currItem >= Elements.Count)
        {
            timer.Stop();
            stopwatch.Stop();
            ReportProgress (curItem, stopwatch.Elapsed.TotalSeconds.ToString("0" + " sec"));
            stopwatch = null;
            MessageBox.Show("The Test is Finish");
            //StartButton.Enabled = true;
            // Use the same approach as that used to report progress.
        }
        else
        {
            // Select item and run it
            ElementControl item = Elements[curItem];
            item.RunElement();
            currItem++;

            ReportProgress (curItem, "sometext"));
        }
    }

这是另一种可能的方法:

    class Task
    {
        public List<ElementControl> Elements = new List<ElementControl>();
    }
    private void buttonStart_Click(object sender, EventArgs e)
    {
        buttonStart.Enabled = false;

        Task task = new Task();
        foreach (ElementControl ele in SequenceListBox.Items)
            task.Elements.Add(ele);

        progressBar1.Maximum = task.Elements.Count;
        backgroundWorker1.RunWorkerAsync(task);
    }
    public delegate void ReportProgressHandler(int value, string text);
    private void ReportProgress(int value, string text)
    {
        if (InvokeRequired)
            Invoke(new ReportProgressHandler(ReportProgress), value, text);
        else
        {
            if(value <= progressBar1.Maximum)
                progressBar1.Value = value;
            label1.Text = text;
        }
    }
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        Task task = e.Argument as Task;
        if (task != null)
        {
            int i = 0;
            foreach (ElementControl ele in task.Elements)
            {
                i++;
                ele.RunElement();
                ReportProgress(i, "sometext + " + i.ToString());
                System.Threading.Thread.Sleep(1000);
            }
            MessageBox.Show("Completed!");
        }
    }