如何在再次按下按钮后实现延迟

时间:2015-07-27 23:14:34

标签: c# winforms

我有一个c#winforms应用程序,我用来调用ASP.net webservice方法来做一些db。

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

大多数情况下整个过程太快而"Request sent.."部分甚至没有显示出来。我想在那里放一个小延迟,这样如果响应速度超过1秒,它应该等待整整秒,然后再下载代码。每次点击后,发送按钮也应停用3秒钟。我需要计时器吗?我试图完成某件事,但对我来说太难了。

4 个答案:

答案 0 :(得分:2)

您可以使用3,000毫秒的计时器。单击该按钮时,禁用该按钮并启动计时器。计时器有一个名为TimeElapsed的事件,您需要订阅该事件,因为您需要再次激活该按钮。

答案 1 :(得分:2)

将button1处理程序标记为async,然后使用await Task.Delay(),如下所示:

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

请注意,无论请求实际占用多长时间,都会等待一秒钟......并在重新启用按钮之前再强制等待两秒钟。

答案 2 :(得分:1)

您可能希望更聪明一点,并减少在3秒钟等待时调用Web服务所花费的时间。所以它不是WS Call + 3秒。

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

修改

请注意,我不支持这种方法,它非常hackish,如果你没有阅读使用业务逻辑层和C#控件绑定,它将导致非常糟糕的编程实践。我提供这个编辑以帮助您继续前进并了解更多信息。 我没有IDE就写过这个,所以可能有错误。

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

答案 3 :(得分:1)

await Task.Delay()是最好的解决方案。如上。 我没有异步等待时尝试的替代方法,并且由于某些原因无法更新.net框架和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;
   }

自定义任务类将如下所示。

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

}