如何分派特定事件

时间:2018-01-15 09:56:08

标签: c# asynchronous

我的WPF .NET 4.5应用程序中有一个事件,每秒最多可触发10次事件,事件是经常不需要的计算数据,因此我正在寻找一种方法来消除不必要的计算如果事件没有被触发3秒钟,则强调并调用该方法。我考虑过使用async这样的功能:

private async Task DoWork()
{
    await Task.Delay(3000);
    ...
}

private void Event()
{
    Task.Run(() => DoWork());
}

我不确定如何优雅地处理不需要的Tasks,即。当用户触发事件时,该事件创建的每个任务都应该终止,并且应该尽可能快。我已尝试使用CancellationToken,但我不确定这是否适用于我的案例

2 个答案:

答案 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); 
        });
    }