RX PropertyChanged GroupBy死锁

时间:2013-03-01 12:05:09

标签: system.reactive inotifypropertychanged

我正在尝试使用Reactive Extensions来限制PropertyChanged通知。有一些使用GroupBy执行此操作的示例,但为每个PropertyName创建了一个订阅。

我想为所有属性处理PropertyChanged事件,我需要为每个PropertyName阻止这些事件。

这是我到目前为止所做的,但它会造成僵局。

ValuesPropertyChanged = Observable.FromEventPattern<PropertyChangedEventArgs>(value, "PropertyChanged")
    .GroupBy(o => o.EventArgs.PropertyName)
    .First()
    .Throttle(TimeSpan.FromSeconds(2))
    .Subscribe(args => HandlePropertyChanged(args.EventArgs.PropertyName));

在对.First()的调用中发生了死锁。

如果我将该行更改为:

,它仍会锁定
.Select(o => o.First())

我也试过

.Select(o => o.FirstAsync())

GroupBy here的示例看起来非常简洁,但我无法将这些示例转换为我的解决方案。

为什么这会导致死锁,我该怎么做才能使其工作?

1 个答案:

答案 0 :(得分:1)

认为这可能是你所追求的:

// assume MyObj : INotifyPropertyChanged, naturally
var value = new MyObj();

Action<string> HandlePropertyChanged = 
    name => Console.WriteLine("Got a change for name:" + name);

// The query
var valuesPropertyChanged = 
    // create from event stream
    from propChange in Observable.FromEventPattern<PropertyChangedEventArgs>(
             value, 
             "PropertyChanged")            
    // group events by property name
    group propChange by propChange.EventArgs.PropertyName into batchByName
    // Throttle the resulting batch
    from throttledByName in batchByName.Throttle(TimeSpan.FromSeconds(1))
    // then select each item of the "throttled output"
    select throttledByName;

valuesPropertyChanged.Subscribe(args => 
    HandlePropertyChanged(args.EventArgs.PropertyName));

for(int i=0;i<10;i++) 
{ 
    value.Value1 = i.ToString(); 
    value.Value2 = (i-1).ToString();
}

输出:

Got a change for name:Value2
Got a change for name:Value1

以下是相同的但有扩展方法:

var valuesPropertyChanged =
    Observable.FromEventPattern<PropertyChangedEventArgs>(
                _vm,
                "PropertyChanged")
                .GroupBy(propchange => propchange.EventArgs.PropertyName)
                .Select(o => o.Throttle(TimeSpan.FromSeconds(1)))
                .Merge();