【问题标题】:Run a code that takes y seconds every x seconds until a button is clicked - C#运行每 x 秒需要 y 秒的代码,直到单击按钮 - C#
【发布时间】:2021-09-02 10:33:42
【问题描述】:

我正在尝试构建一个 Windows 窗体(在 C# 中),它有 2 个按钮 - 启动和停止,它看起来像这样:

(点击开始按钮,停止按钮出现,开始按钮消失,反之亦然)。

单击开始按钮时,我希望我的程序每 x 秒运行一次特定代码,直到单击停止按钮。

我的问题如下:假设运行此特定代码需要 30 秒,我希望这 30 秒计入我的 60 秒间隔。

到目前为止,我的代码所做的是:计数 60 秒,执行某些代码,计数 60 秒,执行某些代码,计数 60 秒等......

我想要它做的是:在开始计算 60 秒时运行某些代码,完成代码,继续计算剩余时间(在我的示例中为 30 秒),再次运行代码(继续计算!)等等...

此外,我的代码在单击停止按钮时不会立即停止,它会再运行代码 1-2 次然后停止。

这是我目前的代码(按钮 1- 开始,按钮 2- 停止):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        static bool exitFlag = false;
        static System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();

        public Form1()
        {
            InitializeComponent();
        }

        private void agTextBox1_Load(object sender, EventArgs e) {}

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

        private void textBox1_TextChanged(object sender, EventArgs e){}

        private void button1_Click(object sender, EventArgs e)
        {
            button1.Visible = false;
            button2.Visible = true;

            myTimer.Tick += new EventHandler(TimerEventProcessor);

            // Sets the timer interval to 60 seconds.
            myTimer.Interval = 60000;
            myTimer.Start();

            // Runs the timer, and raises the event.
            while (exitFlag == false)
            {
                // Processes all the events in the queue.
                Application.DoEvents();
            }

        }


        private void TimerEventProcessor(object sender, EventArgs e)
        {
            //do something that takes x<60 seconds

                myTimer.Stop();

                // checks whether to continue running the timer.
                if (!button1.Visible)
                {
                    // Restarts the timer and increments the counter.
                    myTimer.Enabled = true;
                }
                else
                {
                    // Stops the timer.
                    exitFlag = true;
            }
        }


        private void button2_Click(object sender, EventArgs e)
        {
            button2.Visible = true;
            button1.Visible = true;
        }
    }
}

【问题讨论】:

    标签: c# winforms


    【解决方案1】:

    我想要它做的是:在开始计算 60 秒时运行某些代码,完成代码,继续计算剩余时间(在我的示例中为 30 秒),再次运行代码(继续计算!)等等...

    这是Timer 的默认行为。只需摆脱您在代码中添加的所有额外逻辑即可更改:

    private void TimerEventProcessor(object sender, EventArgs e)
    {
        //do something that takes x<60 seconds
    }
    

    然后只需使用按钮启动/停止计时器:

    private void myStartButton_Click(object sender, EventArgs e)
    {
        myTimer.Start();
    
        // Do your additional visibility/invisibility stuff.
    }
    
    private void myStopButton_Click(object sender, EventArgs e)
    {
        myTimer.Stop();
    
        // Do your additional visibility/invisibility stuff.
    }
    

    你的定时器的配置应该在构造函数中完成,因为不需要在启动/停止时附加/分离事件处理程序:

    public Form1()
    {
        InitializeComponent();
    
        myTimer.Interval = 60000;
        myTimer.Tick += new EventHandler(TimerEventProcessor);
    }
    

    您将不再需要您的exitFlag

    【讨论】:

    • 非常感谢!还有一种方法可以在不等待 60 秒的情况下首次运行代码吗?运行它,启动计时器并从那时起每 60 秒运行一次?
    • @AmitGabay:当然。只需将//do something that takes x&lt;60s 放入它自己的方法中并在启动计时器之前调用该方法一次。
    • 谢谢!你对我帮助很大。
    • @AmitGabay 是的,您的 Form.Timer 将每 60 秒触发一次,没问题,但您必须记住它是单线程的。万一您的代码执行时间超过 60 秒,您的第二次执行将不得不等待轮到它开始,直到第一次执行完成。
    猜你喜欢
    • 2018-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多