C# 队列最新的异步任务
C# Queue Latest Asynchronous Task
我正在开发一个 WPF 应用程序,在该应用程序中,只要数据绑定到滑块的 属性 发生更改,我就需要执行冗长的操作。有没有一种简单的方法可以为这个操作排队异步任务,但确保只有最近排队的任务运行?
您可以使用单个任务,取消它,然后用新任务重新分配它。该任务可以延迟链接以消除滑块:
CancellationTokenSource cancel;
Task task;
...
cancel?.Cancel();
cancel?.Dispose();
cancel = new CancellationTokenSource();
task = Task.Delay(3000, cancel.Token).ContinueWith(...);
我设法通过使用 Task.ContinueWith()
创建任务链来解决我的问题。线程安全计数器确保只有链中的最后一个任务实际运行。
using System;
using System.Threading;
using System.Threading.Tasks;
namespace WpfApp1
{
public class AsyncTaskRunner
{
#region Member Variables
Task m_TaskChain;
int m_TaskCount;
#endregion
#region Constructors
public AsyncTaskRunner()
{
//Initialize the member variables
m_TaskChain = Task.CompletedTask;
m_TaskCount = 0;
}
#endregion
#region Public Methods
public void Run(Action action)
{
//Add a continuation to the task chain using the specified action
Interlocked.Increment(ref m_TaskCount);
m_TaskChain = m_TaskChain.ContinueWith((prevTask) =>
{
//Call the action if we're the last task in the task chain
if (Interlocked.Decrement(ref m_TaskCount) == 0)
{
action();
}
});
}
public async Task WaitAsync()
{
//Wait for the asynchronous task chain to finish
await m_TaskChain;
}
#endregion
}
}
您可以将 Delay
添加到执行此操作的 Binding
。
MSDN 特别指出 Slider
是使用它的好人选:
If you use a data binding to update a data source, you can use the
Delay property to specify an amount of time to pass after the property
changes on the target before the source updates. For example, suppose
that you have a Slider that has its Value property data two-way bound
to a property of a data object and the UpdateSourceTrigger property is
set to PropertyChanged. In this example, when the user moves the
Slider, the source updates for each pixel that the Slider moves. The
source object typically needs the value of the slider only when the
slider's Value stops changing. To prevent updating the source too
often, use Delay to specify that the source should not be updated
until a certain amount of time elapses after the thumb stops moving.
可以这样使用:
<TextBlock Text="{Binding Name, Delay=500}"/>
我正在开发一个 WPF 应用程序,在该应用程序中,只要数据绑定到滑块的 属性 发生更改,我就需要执行冗长的操作。有没有一种简单的方法可以为这个操作排队异步任务,但确保只有最近排队的任务运行?
您可以使用单个任务,取消它,然后用新任务重新分配它。该任务可以延迟链接以消除滑块:
CancellationTokenSource cancel;
Task task;
...
cancel?.Cancel();
cancel?.Dispose();
cancel = new CancellationTokenSource();
task = Task.Delay(3000, cancel.Token).ContinueWith(...);
我设法通过使用 Task.ContinueWith()
创建任务链来解决我的问题。线程安全计数器确保只有链中的最后一个任务实际运行。
using System;
using System.Threading;
using System.Threading.Tasks;
namespace WpfApp1
{
public class AsyncTaskRunner
{
#region Member Variables
Task m_TaskChain;
int m_TaskCount;
#endregion
#region Constructors
public AsyncTaskRunner()
{
//Initialize the member variables
m_TaskChain = Task.CompletedTask;
m_TaskCount = 0;
}
#endregion
#region Public Methods
public void Run(Action action)
{
//Add a continuation to the task chain using the specified action
Interlocked.Increment(ref m_TaskCount);
m_TaskChain = m_TaskChain.ContinueWith((prevTask) =>
{
//Call the action if we're the last task in the task chain
if (Interlocked.Decrement(ref m_TaskCount) == 0)
{
action();
}
});
}
public async Task WaitAsync()
{
//Wait for the asynchronous task chain to finish
await m_TaskChain;
}
#endregion
}
}
您可以将 Delay
添加到执行此操作的 Binding
。
MSDN 特别指出 Slider
是使用它的好人选:
If you use a data binding to update a data source, you can use the Delay property to specify an amount of time to pass after the property changes on the target before the source updates. For example, suppose that you have a Slider that has its Value property data two-way bound to a property of a data object and the UpdateSourceTrigger property is set to PropertyChanged. In this example, when the user moves the Slider, the source updates for each pixel that the Slider moves. The source object typically needs the value of the slider only when the slider's Value stops changing. To prevent updating the source too often, use Delay to specify that the source should not be updated until a certain amount of time elapses after the thumb stops moving.
可以这样使用:
<TextBlock Text="{Binding Name, Delay=500}"/>