Daniel
Daniel

Reputation: 1114

Wait 500ms for user input with ability to cancel or restart

It is a game: User can hover over several Elements, but only if mouse stays there over 500ms a function is called. If user moves the mouse over another Element, countdown from 500ms restarts. But, if user clicks the item countdown just stops until other element is hovered.

This is my attempt but BackgroundWorker can not be restarted since cancellation is async.

public BackgroundWorker bw = new BackgroundWorker();
private void Element_MouseEnter(object sender, MouseEventArgs e)
{
  bw.DoWork += (snd, args) =>
  {
     int i = 500; //500ms
     while (i > 0)
     {
       if (bw.CancellationPending) break;
        Thread.Sleep(10);
        i = i - 10;
     }             
  };
  bw.RunWorkerCompleted += (snd, args) =>
  {
     RunSomething(); //500 ms are out, nothing was clicked
  }
  if (bw.IsBusy) bw.CancelAsync();
  bw.RunWorkerAsync();
}

private void Element_Clicked(object sender, MouseEventArgs e)
{
   bw.CancelAsync();
}

There must be a better way...

Upvotes: 0

Views: 147

Answers (1)

iury
iury

Reputation: 118

private CancellationTokenSource tokenSource;

private async void button1_MouseEnter(object sender, EventArgs e)
{
    if (tokenSource != null)
        tokenSource.Cancel();

    tokenSource = new CancellationTokenSource();
    try
    {
        await Task.Delay(500, tokenSource.Token);
        if (!tokenSource.IsCancellationRequested)
        {
            //
        }
    }
    catch (TaskCanceledException ex) { }
}

private void button1_Click(object sender, EventArgs e)
{
    tokenSource.Cancel();
}

Upvotes: 3

Related Questions