2017-10-05 60 views
0

我正在处理一个WPF应用程序,在该应用程序中,只要数据绑定到滑块的属性发生更改,我就需要执行冗长的操作。有没有简单的方法来为这个操作排队异步任务,但确保只有最近排队的任务运行?C#队列最新异步任务

+0

你问如何为*油门*事件由滑块解雇?这与排队不同。 .NET的机制允许你排列数据进行处理([ActionBlock ](https://msdn.microsoft.com/en-us/library/hh194684(v = vs.110).aspx)),只保留一个([BroadcastBlock ](https://msdn.microsoft.com/en-us/library/hh160447(v = vs.110).aspx)或限制事件流,因此每X或T只有一个事件秒通过[Observable.Throttle](https://msdn.microsoft.com/en-us/library/hh229400(v = vs.103).aspx)。这些*不同。我会说你想节流 –

+0

节流确实听起来像是一个很好的解决方案,你能提供一个我将如何实现的例子吗? –

回答

0

我设法创建一个使用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 
    } 
} 
2

您可以使用单个任务,取消它,然后重新分配一个新任务。该任务可以用延迟被链接去抖滑块:

CancellationTokenSource cancel; 
Task task; 
... 

cancel?.Cancel(); 
cancel?.Dispose(); 
cancel = new CancellationTokenSource(); 
task = Task.Delay(3000, cancel.Token).ContinueWith(...); 
+0

在这种情况下,冗长的任务是将数据推送到设备,因此取消它会产生令人讨厌的副作用 –

+0

@ NeilThiessen我编辑了我的答案,因此它只取消延迟任务。 – mtman

+1

您也可以延迟更新o f绑定,通过添加一个['Delay'](https://msdn.microsoft.com/en-us/library/system.windows.data.bindingbase.delay%28v=vs.110%29.aspx?f = 255&MSPPError = -2147217396)。这对于可以快速更改其值的属性非常有用。延迟计时器从第一次更新开始,但只会在计时器结束后实际更新支持属性,但会以*最新*值进行更新。您可以像这样使用它'''' –

0

您可以将Delay添加到行这Binding

MSDN特别提出Slider作为一个很好的候选人使用它:

如果使用数据绑定来更新数据源,可以使用 延迟属性指定的时间量来传递在源更新之前在目标上更改属性 之后。例如,假设 您有一个Slider,它的Value属性数据双向绑定到 到数据对象的属性,并且UpdateSourceTrigger属性是 设置为PropertyChanged。在这个例子中,当用户移动Slider时,Slider移动的每个像素的源更新。只有当 滑块的值停止更改时,源对象通常才需要滑块的值。为了防止经常更新源 ,使用延迟指定不应更新源 ,直到拇指停止移动后经过一段时间。

它可以像这样使用:

<TextBlock Text="{Binding Name, Delay=500}"/> 
+0

我需要长时间运行的任务,以便在滑块变化时尽可能快地运行。 '延迟'只是防止绑定更新,直到滑块停止移动... –