我有一个后台任务,我按以下方式运行。
这是文本框文本更改事件的附加行为。
我想要的是如果文本被更改然后再次更改,在第二次更改时检查上一个任务是否仍在运行,如果是,则停止它并继续执行最新的任务。
public class FindTextChangedBehavior : Behavior<TextBox>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.TextChanged += OnTextChanged;
}
protected override void OnDetaching()
{
AssociatedObject.TextChanged -= OnTextChanged;
base.OnDetaching();
}
private void OnTextChanged(object sender, TextChangedEventArgs args)
{
var textBox = (sender as TextBox);
if (textBox != null)
{
Task.Factory.StartNew(() =>
{
//Do text search on object properties within a DataGrid
//and populate temporary ObservableCollection with items.
ClassPropTextSearch.init(itemType, columnBoundProperties);
if (itemsSource != null)
{
foreach (object o in itemsSource)
{
if (ClassPropTextSearch.Match(o, searchValue))
{
tempItems.Add(o);
}
}
}
//Copy temporary collection to UI bound ObservableCollection
//on UI thread
Application.Current.Dispatcher.Invoke(new Action(() => MyClass.Instance.SearchMarkers = tempItems));
});
}
}
[编辑]我还没有测试过这个,只是一个可能的模型。
CancellationTokenSource CancellationTokenSource = new CancellationTokenSource();
private void OnTextChanged(object sender, TextChangedEventArgs args)
{
var newCts = new CancellationTokenSource();
var oldCts = Interlocked.Exchange(ref this.CancellationTokenSource, newCts);
if (oldCts != null)
{
oldCts.Cancel();
}
var cancellationToken = newCts.Token;
var textBox = (sender as TextBox);
if (textBox != null)
{
ObservableCollection<Object> tempItems = new ObservableCollection<Object>();
var ui = TaskScheduler.FromCurrentSynchronizationContext();
var search = Task.Factory.StartNew(() =>
{
ClassPropTextSearch.init(itemType, columnBoundProperties);
if (itemsSource != null)
{
foreach (object o in itemsSource)
{
cancellationToken.ThrowIfCancellationRequested();
if (ClassPropTextSearch.Match(o, searchValue))
{
tempItems.Add(o);
}
}
}
}, cancellationToken);
//Still to be considered.
//If it gets to here and it is still updating the UI then
//what to do, upon SearchMarkers being set below do I cancel
//or wait until it is done and continue to update again???
var displaySearchResults = search.ContinueWith(resultTask =>
MyClass.Instance.SearchMarkers = tempItems,
CancellationToken.None,
TaskContinuationOptions.OnlyOnRanToCompletion,
ui);
}
}