我有以下一段代码:
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
委托的执行,从而始终仅对最后一个项目执行处理。
让它工作的最简单方法是使用CancellationToken
Observable.FromAsync<>
重载,并在代码中使用令牌来频繁检查取消:
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()
:通过仅订阅最新的可观察量来展平化,在这种情况下,它还使用属性释放以前的可观察量CancellationToken