简体   繁体   中英

How to implement a delay after a button can be pressed again

I have ac# winforms app that I'm using to invoke an ASP.net webservice method to do some db stuff.

...
namespace WebServiceClient
{
    public partial class Form1 : Form
    {
        Service1ref.Service1 wbsrv = new Service1ref.Service1();
        bool lbl_hid = true;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            label3.ForeColor = System.Drawing.Color.Azure;
            label3.Text = "Request sent...";
            wbsrv.Url = textBox1.Text;
            string response = wbsrv.GenerateRandomSensorData(textBox2.Text);

            label3.Text = response;
            if (label3.Text.Contains('7'))
                label3.ForeColor = System.Drawing.Color.Green;
            else
                label3.Text = "Error";
                label3.ForeColor = System.Drawing.Color.Red;
            if (lbl_hid == true)
            {
                label3.Show();
                lbl_hid = false;
            }
        }
...

Most of the time the whole process is too fast and the "Request sent.." part doesn't even show. I would like to put a small delay there so that if the response is faster than 1 sec it should wait for the whole second before going down the code. Also the Send button should be deactivated for 3 seconds after each hit. Will I need timers? I have tried to get something done but it's too hard for me atm.

You can use a timer with 3,000 milliseconds. When the button is clicked you disable the button and start the timer. Timers have an event called TimeElapsed and you'll need to subscribe to that event because you need to activate the button again.

Mark the button1 handler with async , then use await Task.Delay() like this:

    private async void button1_Click(object sender, EventArgs e)
    {
        button1.Enabled = false;

        label3.ForeColor = System.Drawing.Color.Azure;
        label3.Text = "Request sent...";
        wbsrv.Url = textBox1.Text;
        string response = wbsrv.GenerateRandomSensorData(textBox2.Text);
        await Task.Delay(1000);

        label3.Text = response;
        if (label3.Text.Contains('7'))
        { 
            label3.ForeColor = System.Drawing.Color.Green;
        }
        else
        {
            label3.Text = "Error";
            label3.ForeColor = System.Drawing.Color.Red;
        }

        if (lbl_hid == true)
        {
            label3.Show();
            lbl_hid = false;
        }

        await Task.Delay(2000);
        button1.Enabled = true;
    }

Note that this waits an additional one second regardless of how long the request actually took...and forces an additional two second wait after that before re-enabling the button.

You might want to be a bit smarter and deduct the time spent calling the webservice off the 3 second wait. So its not WS Call + 3 seconds.

private async void button1_Click(object sender, EventArgs e)
{
    //Record the time when button was clicked
    DateTime timeButtonWasClicked = DateTime.Now;

    button1.Enabled = false;
    label3.ForeColor = System.Drawing.Color.Azure;
    label3.Text = "Request sent...";

    //Force the label to be repainted
    label3.Invalidate();

    wbsrv.Url = textBox1.Text;
    string response = wbsrv.GenerateRandomSensorData(textBox2.Text);

    //If the user has waited less than 3 seconds, 
    //make them wait the difference, otherwise 
    //dont force users to wait at least 6 or so seconds
    TimeSpan ts = DateTime.Now - timeButtonWasClicked;
    if (ts.Seconds < 3) await Task.Delay(TimeSpan.FromSeconds(3).Subtract(ts));

    label3.Text = response;
    if (label3.Text.Contains('7')) { 
        label3.ForeColor = System.Drawing.Color.Green;
    }
    else {
        label3.Text = "Error";
        label3.ForeColor = System.Drawing.Color.Red;
    }

    if (lbl_hid) {  //Dont bother testing Booleans for "== true"
        label3.Show();
        lbl_hid = false;
    }
    button1.Enabled = true;
}

Edit:

Note that I dont endorse this method, its very hackish and if you dont read up on using a Business Logic Layer and C# Control Binding that it will lead to very bad programming practices. I provide this edit to help you move on and learn more. I've written this without an IDE so there maybe bugs.

//Declare a timer control
private static System.Timers.Timer aTimer;

//We need to check when the response is populated between two methods, so I've declared it as a private member variable
private string response = string.Empty;

private void button1_Click(object sender, EventArgs e)
{
    button1.Enabled = false;
    label3.ForeColor = System.Drawing.Color.Azure;
    label3.Text = "Request sent...";

    //Force the label to be repainted
    label3.Invalidate();

    //Instantiate the timer and set a one second interval.
    aTimer = new System.Timers.Timer();
    aTimer.Interval = 1000;

    // Hook up the Elapsed event for the timer. 
    aTimer.Elapsed += OnTimedEvent;

    // Start the timer
    aTimer.Enabled = true;

    wbsrv.Url = textBox1.Text;
    response = wbsrv.GenerateRandomSensorData(textBox2.Text);

}

private static void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
{
    //Check the response string variable is NOT empty
    if  (!string.IsNullOrEmpty(response)) 
    {
       label3.Text = response;
       // Stop the timer
       aTimer.Enabled = false;
    }
    else
    {
       return;
    }

    if (label3.Text.Contains('7')) { 
        label3.ForeColor = System.Drawing.Color.Green;
    }
    else {
        label3.Text = "Error";
        label3.ForeColor = System.Drawing.Color.Red;
    }

    if (lbl_hid) { 
        label3.Show();
        lbl_hid = false;
    }
    button1.Enabled = true;
}

await Task.Delay() is the best sol. as above. an alternate approach I tried when I do not have async await,and due to some reasons can't update .net framework and visual studio.

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

        label3.ForeColor = System.Drawing.Color.Azure;
        label3.Text = "Request sent...";
        wbsrv.Url = textBox1.Text;
        string response = wbsrv.GenerateRandomSensorData(textBox2.Text);
        // Custom Task Class 
        Task.Delay(TimeSpan.FromSeconds(1)).ContinueWith(AfteDelay); 

    }

   private void AfterDelay(){

            label3.Text = response;
            if (label3.Text.Contains('7'))
            { 
                label3.ForeColor = System.Drawing.Color.Green;
            }
            else
            {
                label3.Text = "Error";
                label3.ForeColor = System.Drawing.Color.Red;
            }

            if (lbl_hid == true)
            {
                label3.Show();
                lbl_hid = false;
            }

            button1.Enabled = true;
   }

the Custom Task Class will look like this.

   using System.Windows.Forms.Timer;

  public class Task
{
    Timer timer;
    public static Task Delay(TimeSpan timeSpan)
    {
        Task task = new Task();
        task.timer = new Timer();
        task.timer.Interval = Convert.ToInt32(timeSpan.TotalMilliseconds);
        return task;

    }
    private Task()
    {

    }
    public static Task Delay(int miliSeconds)
    {
        Task task = new Task();
        task.timer = new Timer();
        task.timer.Interval = miliSeconds;
        return task;

    }
    public static void Run(Action action)
    {
        Timer timer = new Timer();
        timer.Interval = 1;
        timer.Enabled = true;
        timer.Tick += delegate
        {
            timer.Stop();
            timer = null;
            action();
        };
    }
    EventHandler elapsed;
    public void ContinueWith(Action action)
    {

        timer.Enabled = true;
        elapsed = delegate
        {
            Stop();
            action();
        };
        //bind the event
        timer.Tick += elapsed;


    }
    private void handleEvent(Action action)
    {

    }
    public void Stop()
    {
        timer.Stop();
        timer.Enabled = false;
        //unbind the event
        if (elapsed != null)
        {
            timer.Tick -= elapsed;
        }
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM