我有以下代码:
Observable.FromEventPattern<PropertyChangingEventArgs>(_parent, "PropertyChanged")
.Subscribe(ep =>
{
switch (ep.EventArgs.PropertyName)
{
case "ValorBlurMenor":
LoadBlurMenor();
break;
case "ValorBlurMaior":
LoadBlurMaior();
break;
}
});
我的问题是ValorBlurMenor
和ValorBlurMaior
是通过WPF滑块更改的,LoadBlurMaior()
和LoadBlurMenor()
需要一些时间来评估。
如果新项目到达,我正在寻找一种方法来中断/取消项目的Subscribe
代表的执行,因此始终只对最后一项执行处理。
答案 0 :(得分:3)
让它运行的最简单方法是使用Observable.FromAsync<>
重载使用CancellationToken
并使用代码中的令牌来经常检查取消:
public class PlainNotifiable : INotifyPropertyChanged
{
private bool takeFiveSeconds;
private bool takeTenSeconds;
public event PropertyChangedEventHandler PropertyChanged;
public bool TakeFiveSeconds
{
get => this.takeFiveSeconds;
set
{
this.takeFiveSeconds = value;
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.TakeFiveSeconds)));
}
}
public bool TakeTenSeconds
{
get => this.takeTenSeconds;
set
{
this.takeTenSeconds = value;
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.TakeTenSeconds)));
}
}
public async Task TakeSomeTime(int seconds, CancellationToken token = default(CancellationToken))
{
Trace.TraceInformation("Started waiting {0} seconds", seconds);
await Task.Delay(seconds * 1000, token);
Trace.TraceInformation("Stoped waiting {0} seconds", seconds);
}
}
public static async void Test()
{
var test = new PlainNotifiable();
async Task<Unit> propertyNameToLongTask(EventPattern<PropertyChangedEventArgs> args, CancellationToken token)
{
switch (args.EventArgs.PropertyName)
{
case nameof(test.TakeFiveSeconds):
await test.TakeSomeTime(5, token);
break;
case nameof(test.TakeTenSeconds):
await test.TakeSomeTime(10, token);
break;
}
return Unit.Default;
}
Observable.FromEventPattern<PropertyChangedEventArgs>(test, nameof(test.PropertyChanged))
.Select(x => Observable.FromAsync(token => propertyNameToLongTask(x, token)))
.Switch()
.Subscribe(x => Trace.TraceInformation("Beep boop"));
Trace.TraceInformation("Started sending notifications");
await Task.Delay(1000);
test.TakeTenSeconds = true;
await Task.Delay(2000);
test.TakeFiveSeconds = true;
Trace.TraceInformation("Finished sending notifications");
}
它提供以下输出:
SandBox.exe Information: 0 : Started sending notifications
SandBox.exe Information: 0 : Started waiting 10 seconds
SandBox.exe Information: 0 : Started waiting 5 seconds
SandBox.exe Information: 0 : Finished sending notifications
Exception thrown: 'System.Threading.Tasks.TaskCanceledException' in mscorlib.dll
Exception thrown: 'System.Threading.Tasks.TaskCanceledException' in mscorlib.dll
SandBox.exe Information: 0 : Stoped waiting 5 seconds
SandBox.exe Information: 0 : Beep boop
要点是:
Observable.FromAsync()
:使用正确的CancellationToken
支持Switch()
:仅通过订阅最新的observable进行Flatenize,它还使用属性处理前一个observable,在本例中为CancellationToken