C# 如何分派由特定事件创建的每个以前的任务

C# 如何分派由特定事件创建的每个以前的任务,c#,asynchronous,C#,Asynchronous,我的WPF.NET4.5应用程序中有一个事件,每秒最多可以触发10次,该事件正在计算不需要的数据,因此我正在寻找一种方法来消除不必要的计算压力,并在事件未触发3秒时调用该方法。我考虑过使用async这样的功能: private async Task DoWork() { await Task.Delay(3000); ... } private void Event() { Task.Run(() => DoWork()); } 我真的不确定如何优雅地处理不需要

我的WPF.NET4.5应用程序中有一个事件,每秒最多可以触发10次,该事件正在计算不需要的数据,因此我正在寻找一种方法来消除不必要的计算压力,并在事件未触发3秒时调用该方法。我考虑过使用
async
这样的功能:

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

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

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

您可以使用
CancellationTokenSource
让任务中的代码知道它已被取消:

private CancellationTokenSource CancellationTokenSource { get; } = new CancellationTokenSource ();
让我们改变一下:

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

现在,如果需要,我们可以取消任务:

CancellationTokenSource.Cancel();

Task.Delay
将观察CancellationToken,如果它处于已取消状态,它将中止任务执行。稍后在代码中,我们将检查是否需要执行任何操作。

您可以使用
CancellationTokenSource
让任务中的代码知道它已被取消:

private CancellationTokenSource CancellationTokenSource { get; } = new CancellationTokenSource ();
让我们改变一下:

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

现在,如果需要,我们可以取消任务:

CancellationTokenSource.Cancel();

Task.Delay
将观察CancellationToken,如果它处于已取消状态,它将中止任务执行。稍后在代码中,我们检查是否需要执行任何操作。

这是我基于@Fabjan answer的解决方案

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

这是我基于@Fabjan answer的解决方案

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

制作一个bool
isRunning
。如果
isRunning
为真->返回。一旦开始任务,将bool设置为true;一旦完成任务,将bool设置为false。不幸的是,我希望执行最新的任务,如果未执行上一个任务,您的建议将阻止任何输入任务。当新任务到达时,我想覆盖以前的任务使bool
正在运行
。如果
isRunning
为真->返回。一旦开始任务,将bool设置为true;一旦完成任务,将bool设置为false。不幸的是,我希望执行最新的任务,如果未执行上一个任务,您的建议将阻止任何输入任务。我想在新任务到达时覆盖以前的任务谢谢!这就是我需要的方向。唯一的问题是,在4.5中,您不能直接将值分配给属性,
Task.Delay
在取消时会引发异常(TaskCanceledException),而且我们在这里共享一个取消令牌,因此一旦运行
Cancel
方法,每次进一步的事件都会取消令牌hanks!这就是我需要的方向。唯一的问题是,在4.5中,您不能直接将值分配给属性,
Task.Delay
在取消时会引发异常(TaskCanceledException),而且我们在这里共享一个取消令牌,因此一旦我们运行
Cancel
方法,每次后续事件都会取消该令牌