C# 如何使用1000个观察者高效地运行Observable.Where()?
我是Rx的新手,我绝对喜欢它。我发现代码的现有部分可以通过使用它大大简化。我遇到了一个性能问题,如果有一位大师能帮助我,我将不胜感激 以前,我有一个手动实现的observer类,它接受订阅和一个键过滤器。当事件进入类时,它将使用提供的键查找哪些观察器需要回调。这是一个非常简化的代码版本:C# 如何使用1000个观察者高效地运行Observable.Where()?,c#,performance,system.reactive,C#,Performance,System.reactive,我是Rx的新手,我绝对喜欢它。我发现代码的现有部分可以通过使用它大大简化。我遇到了一个性能问题,如果有一位大师能帮助我,我将不胜感激 以前,我有一个手动实现的observer类,它接受订阅和一个键过滤器。当事件进入类时,它将使用提供的键查找哪些观察器需要回调。这是一个非常简化的代码版本: class OldClass { private Dictionary<string, List<Action<UsefulInfo>> _callbacks =
class OldClass
{
private Dictionary<string, List<Action<UsefulInfo>> _callbacks =
new Dictionary<string, List<Action<UsefulInfo>>();
void Subscribe(string key, Action<UsefulInfo> callback)
{
_callbacks[key].Add(callback);
}
// Some event happens that we want to notify subscribers about
void EventHandler(object sender, SomeEventArgs e)
{
// Create object for callbacks
UsefulInfo info = CreateUsefulInfo(e);
string key = info.Key;
// Look up callbacks for key
_callbacks[key].ForEach(callback => callback(info));
}
}
class-OldClass
{
私有词典您可以通过在Where'd
序列上使用共享观察者,然后在IConnectableObservable
上使用来更智能地管理对源的订阅
在您的场景中,我想象您将这些“已发布”的观测值存储在字典中,并根据需要添加到它们中
以下是一个基本实现:
class NewClass
{
private Subject<UsefulInfo> _subject = new Subject<UsefulInfo>();
private IDictionary<string, IObservable<UsefulInfo>> _keyedObservables;
public NewClass()
{
_keyedObservables = new Dictionary<string, IObservable<UsefulInfo>>();
}
IDisposable Subscribe(string key, Action<UsefulInfo> callback)
{
// NOT threadsafe for concurrent subscriptions!
if (!_keyedObservables.Contains(key))
{
var keyedAndPublished = _subject.Where(x => x.Key == key)
.Publish()
.RefCount();
_keyedObservables.Add(key, keyedAndPublished);
}
return _keyedObservables[key].Subscribe(callback);
}
// Some event happens that we want to notify subscribers about
void EventHandler(object sender, SomeEventArgs e)
{
UsefulInfo info = CreateUsefulInfo(e);
_observable.OnNext(info);
}
}
class新类
{
私人主语_Subject=新主语();
私有IDictionary _keyedObservable;
公共类()
{
_keyedObservables=新字典();
}
IDisposable订阅(字符串键、操作回调)
{
//对于并发订阅,不是线程安全的!
if(!\u keyedObservables.Contains(key))
{
var keyedAndPublished=\u subject.Where(x=>x.Key==Key)
.Publish()
.RefCount();
_添加(键、键和已发布);
}
返回_keyedObservables[key]。订阅(回调);
}
//发生了一些我们想通知订阅者的事件
void EventHandler(对象发送方,SomeEventArgs e)
{
UsefulInfo=CreateUsefulInfo(e);
_observable.OnNext(信息);
}
}
谢谢你花时间回答这个问题,Richard。我是Rx的新手,所以你介意稍微扩展一下吗?@JamesD-我添加了一个实现。这可能有助于进一步解释IConnectableObservable。你是个天才,这很有意义。非常感谢你花时间。我刚刚将代码粘贴到一个简单的测试项目中,然后运行它。它确实会为每个键共享观察者。问题是,大多数调用的观察者都有不同的键。因此,对于每个键,主题上的Where func仍然会调用一次,每个事件都会调用1000次。这有意义吗?@JamesD-考虑到有1000个唯一键,我认为Rx不能做你想做的事情在使用单个主题之后。我建议为每个键创建一个主题,并将其存储在字典中。
class NewClass
{
private Subject<UsefulInfo> _subject = new Subject<UsefulInfo>();
private IDictionary<string, IObservable<UsefulInfo>> _keyedObservables;
public NewClass()
{
_keyedObservables = new Dictionary<string, IObservable<UsefulInfo>>();
}
IDisposable Subscribe(string key, Action<UsefulInfo> callback)
{
// NOT threadsafe for concurrent subscriptions!
if (!_keyedObservables.Contains(key))
{
var keyedAndPublished = _subject.Where(x => x.Key == key)
.Publish()
.RefCount();
_keyedObservables.Add(key, keyedAndPublished);
}
return _keyedObservables[key].Subscribe(callback);
}
// Some event happens that we want to notify subscribers about
void EventHandler(object sender, SomeEventArgs e)
{
UsefulInfo info = CreateUsefulInfo(e);
_observable.OnNext(info);
}
}