如何使用Task闪烁标签

本文关键字:标签 闪烁 Task 何使用 | 更新日期: 2024-04-23 15:30:53

我想要一个扩展方法来闪烁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();                
   }
}

如果我有两个按钮,一个带"闪烁",一个带有"停止",一切都很好。。。我的问题是,如果我有一个带有以下代码的按钮。。。

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

在使用Blink方法开始第二个任务之前,我需要一种方法来取消第一个任务。。。

如何使用Task闪烁标签

目前的解决方案存在一些问题。首先,取消令牌是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