如何使用Task使标签闪烁

时间:2015-02-12 12:36:35

标签: c# .net winforms

我想要一种扩展方法来在Windows窗体上闪烁标签......

所以我写了下面的代码......

private static ConcurrentBag<Task> Tasks = new ConcurrentBag<Task>();
private static CancellationTokenSource cts = null;

public static void Blink(this Label label, string text)
{
    cts = new CancellationTokenSource();
    Task task = new Task(async () =>
    {
        label.Invoke((Action)(() =>
        {
            label.Text = text;
            label.Visible = true;
        }));
        while (true)
        {
            label.Invoke((Action)(() => { label.Visible = !label.Visible; }));
            if (cts.IsCancellationRequested)
            { 
                break; 
            }
            await Task.Delay(600);
        }
        label.Invoke((Action)(() => { label.Visible = false; }));
    },cts.Token);

    Tasks.Add(task);
    task.Start();
}

还有一些代码要停止......

public static void Stop(this Label label)
{
   if (cts != null)
   {
       cts.Cancel();                
   }
}

如果我有两个按钮,其中一个带有Blink,另一个带有Stop,一切都很好...... 我的问题是,如果我有一个带有以下代码的按钮......

label1.Blink("Hello World!");
label1.Blink("Hi");

我需要一种方法来取消第一个任务,然后在Blink方法开始第二个任务...

1 个答案:

答案 0 :(得分:0)

解决方案存在一些问题。例如,取消令牌为static,因此它们将在所有闪烁标签之间共享。另一方面,使用任务构造函数StartControl.Invoke,代码过于复杂。

更简单的方法如下:

public static Tuple<Task, CancellationTokenSource> Blink(this Label label)
{
  var cts = new CancellationTokenSource();
  var task = BlinkAsync(label, cts.Token);
  return Tuple.Create(task, cts);
}

private static Task BlinkAsync(Label label, CancellationToken cancellationToken)
{
  label.Visible = true;
  while (true)
  {
    label.Visible = !label.Visible;
    cancellationToken.ThrowIfCancellationRequested();
    await Task.Delay(600);
  }
}

用法:

var runningBlink = label.Blink();
...
runningBlink.Item2.Cancel(); // to stop