我的WPF .NET 4.5应用程序中有一个事件,每秒最多可触发10次事件,事件是经常不需要的计算数据,因此我正在寻找一种方法来消除不必要的计算如果事件没有被触发3秒钟,则强调并调用该方法。我考虑过使用async
这样的功能:
private async Task DoWork()
{
await Task.Delay(3000);
...
}
private void Event()
{
Task.Run(() => DoWork());
}
我不确定如何优雅地处理不需要的Tasks
,即。当用户触发事件时,该事件创建的每个任务都应该终止,并且应该尽可能快。我已尝试使用CancellationToken
,但我不确定这是否适用于我的案例
答案 0 :(得分:2)
您可以使用CancellationTokenSource
让任务中的代码知道它已被取消:
private CancellationTokenSource CancellationTokenSource { get; } = new CancellationTokenSource ();
让我们改变:
private async Task DoWork()
{
await Task.Delay(3000);
...
}
要:
private async Task DoWork(int timeout = 3000)
{
await Task.Delay(timeout, CancellationTokenSource.Token);
if(!CancellationTokenSource.Token.IsCancellationRequested)
{
...
}
}
现在我们可以根据需要取消任务:
CancellationTokenSource.Cancel();
Task.Delay
将观察CancellationToken,如果它处于Canceled状态,它将中止任务执行。稍后在代码中我们检查是否需要做任何事情。
答案 1 :(得分:1)
这是我基于@Fabjan回答的解决方案。
private static void RunSingleTask(ref CancellationTokenSource cts, int delay, Action func)
{
if (cts != null)
{
cts.Cancel();
cts.Dispose();
}
cts = new CancellationTokenSource();
var token = cts.Token;
Task.Run(async () =>
{
try
{
await Task.Delay(delay, token);
}
catch (TaskCanceledException)
{
return;
}
await Application.Current.Dispatcher.BeginInvoke(func);
});
}