我想要一种扩展方法来在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方法开始第二个任务...
答案 0 :(得分:0)
解决方案存在一些问题。例如,取消令牌为static
,因此它们将在所有闪烁标签之间共享。另一方面,使用任务构造函数Start
和Control.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