Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “变更流”); _itemsSubscription=\u itemsStream.Connect(); } 公共停车场() { _changeSubscription.Dispose(); _itemsSubscription.Dispose(); } } 公共类项目 { public int Id{get;private set;} 公共int值{get;private set;} 公共项(整数id、整数值) { Id=Id; 价值=价值; } 公共布尔值已更改(项目比较项) { 返回此.Value!=compareItem.Value; } 公共重写字符串ToString() { 返回$“Item:Id={Id}Value={Value}”; } } 公共静态类RxExtensions { 公共静态IDisposable SubscribeConsole(此IObservable可观察,字符串名称=) { 返回observable.Subscribe(新控制台观察者(名称)); } /// ///向控制台记录可观测对象上/由可观测对象完成的订阅和发射 ///每个日志消息还包括它发生的线程 /// ///可观测类型 ///要记录的可观测数据。 ///将在每次通知之前添加的可选名称前缀 /// 公共静态IObservable LogConsoleWithThread(此IObservable observable,字符串名称=) { 返回可观察的延迟(()=> { WriteLine(“{0}订阅发生在线程:{1}”,名称,Thread.CurrentThread.ManagedThreadId); 返回可观察到的( x=>Console.WriteLine(“{0}-OnNext({1})线程:{2}”,名称,x,Thread.CurrentThread.ManagedThreadId), ex=> { WriteLine(“{0}-OnError线程:{1}”,名称,Thread.CurrentThread.ManagedThreadId); Console.WriteLine(“\t{0}”,ex); }, ()=>Console.WriteLine(“{0}-OnCompleted()线程{1}”,名称,Thread.CurrentThread.ManagedThreadId)); }); } } /// ///每次OnNext、OnError或OnComplete发生时输出到控制台的观察者 /// /// 公共类控制台观察服务器:IObserver { 私有只读字符串\u名称; 公共控制台观察服务器(字符串名称=“”) { _名称=名称; } 公共void OnNext(T值) { WriteLine(“{0}-OnNext({1})”,_name,value); } 公共无效OnError(异常错误) { WriteLine({0}-OnError:,_name); WriteLine(“\t{0}”,错误); } 未完成的公共无效() { WriteLine(“{0}-OnCompleted()”,_name); } } }_C#_System.reactive_Rx.net - Fatal编程技术网

C# “变更流”); _itemsSubscription=\u itemsStream.Connect(); } 公共停车场() { _changeSubscription.Dispose(); _itemsSubscription.Dispose(); } } 公共类项目 { public int Id{get;private set;} 公共int值{get;private set;} 公共项(整数id、整数值) { Id=Id; 价值=价值; } 公共布尔值已更改(项目比较项) { 返回此.Value!=compareItem.Value; } 公共重写字符串ToString() { 返回$“Item:Id={Id}Value={Value}”; } } 公共静态类RxExtensions { 公共静态IDisposable SubscribeConsole(此IObservable可观察,字符串名称=) { 返回observable.Subscribe(新控制台观察者(名称)); } /// ///向控制台记录可观测对象上/由可观测对象完成的订阅和发射 ///每个日志消息还包括它发生的线程 /// ///可观测类型 ///要记录的可观测数据。 ///将在每次通知之前添加的可选名称前缀 /// 公共静态IObservable LogConsoleWithThread(此IObservable observable,字符串名称=) { 返回可观察的延迟(()=> { WriteLine(“{0}订阅发生在线程:{1}”,名称,Thread.CurrentThread.ManagedThreadId); 返回可观察到的( x=>Console.WriteLine(“{0}-OnNext({1})线程:{2}”,名称,x,Thread.CurrentThread.ManagedThreadId), ex=> { WriteLine(“{0}-OnError线程:{1}”,名称,Thread.CurrentThread.ManagedThreadId); Console.WriteLine(“\t{0}”,ex); }, ()=>Console.WriteLine(“{0}-OnCompleted()线程{1}”,名称,Thread.CurrentThread.ManagedThreadId)); }); } } /// ///每次OnNext、OnError或OnComplete发生时输出到控制台的观察者 /// /// 公共类控制台观察服务器:IObserver { 私有只读字符串\u名称; 公共控制台观察服务器(字符串名称=“”) { _名称=名称; } 公共void OnNext(T值) { WriteLine(“{0}-OnNext({1})”,_name,value); } 公共无效OnError(异常错误) { WriteLine({0}-OnError:,_name); WriteLine(“\t{0}”,错误); } 未完成的公共无效() { WriteLine(“{0}-OnCompleted()”,_name); } } }

C# “变更流”); _itemsSubscription=\u itemsStream.Connect(); } 公共停车场() { _changeSubscription.Dispose(); _itemsSubscription.Dispose(); } } 公共类项目 { public int Id{get;private set;} 公共int值{get;private set;} 公共项(整数id、整数值) { Id=Id; 价值=价值; } 公共布尔值已更改(项目比较项) { 返回此.Value!=compareItem.Value; } 公共重写字符串ToString() { 返回$“Item:Id={Id}Value={Value}”; } } 公共静态类RxExtensions { 公共静态IDisposable SubscribeConsole(此IObservable可观察,字符串名称=) { 返回observable.Subscribe(新控制台观察者(名称)); } /// ///向控制台记录可观测对象上/由可观测对象完成的订阅和发射 ///每个日志消息还包括它发生的线程 /// ///可观测类型 ///要记录的可观测数据。 ///将在每次通知之前添加的可选名称前缀 /// 公共静态IObservable LogConsoleWithThread(此IObservable observable,字符串名称=) { 返回可观察的延迟(()=> { WriteLine(“{0}订阅发生在线程:{1}”,名称,Thread.CurrentThread.ManagedThreadId); 返回可观察到的( x=>Console.WriteLine(“{0}-OnNext({1})线程:{2}”,名称,x,Thread.CurrentThread.ManagedThreadId), ex=> { WriteLine(“{0}-OnError线程:{1}”,名称,Thread.CurrentThread.ManagedThreadId); Console.WriteLine(“\t{0}”,ex); }, ()=>Console.WriteLine(“{0}-OnCompleted()线程{1}”,名称,Thread.CurrentThread.ManagedThreadId)); }); } } /// ///每次OnNext、OnError或OnComplete发生时输出到控制台的观察者 /// /// 公共类控制台观察服务器:IObserver { 私有只读字符串\u名称; 公共控制台观察服务器(字符串名称=“”) { _名称=名称; } 公共void OnNext(T值) { WriteLine(“{0}-OnNext({1})”,_name,value); } 公共无效OnError(异常错误) { WriteLine({0}-OnError:,_name); WriteLine(“\t{0}”,错误); } 未完成的公共无效() { WriteLine(“{0}-OnCompleted()”,_name); } } },c#,system.reactive,rx.net,C#,System.reactive,Rx.net,您可能需要一个专业的发布运营商,因为现有的(Publish、PublishLast和Replay)太窄或太宽,无法满足您的需要。因此,您需要使用操作符,它提供了一个自定义重播主题,该主题只缓冲每个键的最后一个元素。以下是该主题的基本实现: public class ReplayLastPerKeySubject<T, TKey> : ISubject<T> { private readonly Func<T, TKey> _keySelector;

您可能需要一个专业的发布运营商,因为现有的(
Publish
PublishLast
Replay
)太窄或太宽,无法满足您的需要。因此,您需要使用操作符,它提供了一个自定义重播主题,该主题只缓冲每个键的最后一个元素。以下是该主题的基本实现:

public class ReplayLastPerKeySubject<T, TKey> : ISubject<T>
{
    private readonly Func<T, TKey> _keySelector;
    private readonly ReplaySubject<ReplaySubject<T>> _subjects;
    private readonly IObservable<T> _mergedSubjects;
    private readonly Dictionary<TKey, ReplaySubject<T>> _perKey;

    public ReplayLastPerKeySubject(Func<T, TKey> keySelector)
    {
        _keySelector = keySelector;
        _subjects = new ReplaySubject<ReplaySubject<T>>();
        _mergedSubjects = _subjects.Merge();
        _perKey = new Dictionary<TKey, ReplaySubject<T>>();
    }

    public void OnNext(T value)
    {
        var key = _keySelector(value);
        ReplaySubject<T> subject;
        if (!_perKey.TryGetValue(key, out subject))
        {
            subject = new ReplaySubject<T>(1);
            _perKey.Add(key, subject);
            _subjects.OnNext(subject);
        }
        subject.OnNext(value);
    }

    public void OnCompleted()
    {
        // All subjects, inner and outer, must be completed
        _subjects.OnCompleted();
        _subjects.Subscribe(subject => subject.OnCompleted());
    }

    public void OnError(Exception error)
    {
        // Faulting the master (outer) subject is enough
        _subjects.OnError(error);
    }

    public IDisposable Subscribe(IObserver<T> observer)
    {
        return _mergedSubjects.Subscribe(observer);
    }
}
最后,您可以使用
Where
操作符为特定密钥创建更改流:

var changeStream13 = published.Where(x => x.Id == 13);

您是否考虑过使用操作符而不是?是的,我考虑过所有外部订阅者都可以使用Where操作符订阅他们感兴趣的特定Id的ChangeStream,但这不允许我在某个特定Id是延迟订阅者时重播最后一次更改。ChangeStream可能会转到[1][2][2][3]等。对Id 1感兴趣的已故订户将如何重播Id 1的上一次更改?谢谢,此解决方案在初始阶段按要求和预期工作testing@Triplegang我主要关心的是在
OnNext
中是否需要添加同步(
lock
),
OnCompleted
OnError
方法。可能不需要。你可以添加它,以确保不会发生任何坏事。或者,您也可以附加到源可观察对象。我将查看竞争条件并尝试Syncronize。实际上,我在组管道中添加了一个TakeUntil条件,该条件会导致组上的未完成项,但未完成项不会传播到ReplayLastPerKeySubject中的未完成项。这是预期的行为吗?@Triplegang否,预期的行为是为了传播
OnCompleted
。如果它没有传播,那么
ReplayLastPerKeySubject
就是有缺陷的。你能用最少的错误复制共享一个链接吗?
var published = YourObservable
    .Multicast(new ReplayLastPerKeySubject<Item, int>(x => x.Id)))
    .RefCount();
var changeStream13 = published.Where(x => x.Id == 13);