如何跳过/暂停在c#中发送给观察者的通知



我使用事件和委托实现了一个观察者模式。该程序正在接收和处理大量数据(每秒约3000条消息(,但在某个时候,它开始发送带有延迟时间戳的消息,我正在努力解决这个问题。在我看来,我有三个主要的课程可以完成这项工作:

public class MessageTracker : IObservable<MessageEventArgs>
{
private List<IObserver<MessageEventArgs>> observers;
public MessageTracker()
{
observers = new List<IObserver<MessageEventArgs>>();
}
private static readonly MessageTracker mInstance = new MessageTracker();
private static MessageTracker getInstance() => mInstance;
private class Unsubscriber : IDisposable
{
private List<IObserver<MessageEventArgs>> _observers;
private IObserver<MessageEventArgs> _observer;
public Unsubscriber(List<IObserver<MessageEventArgs>> observers, IObserver<MessageEventArgs> observer)
{
this._observers = observers;
this._observer = observer;
}
public void Dispose() 
{
if (! (_observer == null)) _observers.Remove(_observer);
}
}
public IDisposable Subscribe(IObserver<MessageEventArgs> observer)
{
if (! observers.Contains(observer))
observers.Add(observer);
return new Unsubscriber(observers, observer);
}
public void MessageTrack(MessageEventArgs msg) {
observers.AsParallel().ForAll(observer =>
{
if (msg is null) 
observer.OnError(new ArgumentException("MessageError."));
else
observer.OnNext(msg);
});
}
public void EndMessageTrans(){
foreach(var observer in observers.ToArray())
if (observers.Contains(observer))
observer.OnCompleted();
observers.Clear();
}
}

public class MessageReporter : IObserver<MessageEventArgs>
{
private IDisposable unsubscriber;
public MessageReporter()
{ }
public event EventHandler<MessageEventArgs> OnNextMessage;

public virtual void Subscribe(IObservable<MessageEventArgs> provider)
{
if (provider != null)
unsubscriber = provider.Subscribe(this);
}
public void OnCompleted()
{
this.Unsubscribe();
}
public void OnError(Exception error)
{
}
public void OnNext(MessageEventArgs value)
{
if (OnNextMessage != null)
{
OnNextMessage?.Invoke(this, value);
}
}
public virtual void Unsubscribe()
{
unsubscriber.Dispose();
}
}
public sealed class MessageDataWorker 
{
private readonly bool mSubscribeAll;
private readonly IEnumerable<string> mMessages;
public MessageDataWorker(IEnumerable<string> messages)
{
mMessages = messages;
if ((mMessages?.Count() ?? 0) == 0)
mSubscribeAll = true;
}
public override void DoWork()
{

var messageReporter = new MessageReporter();
messageReporter.OnNextMessage += OnNewMessageReceived;
messageReporter.Subscribe(MessageTracker.GetInstance());
while (!mShouldStop.WaitOne(100)) ;
MessageReporter.Unsubscribe();
}
private void OnNewMessageReceived(object sender, MessageEventArgs e)
{
if (!mSubscribeAll && !mMessages.Contains(e.Message))
return;
string message = "Message|" +
$"{e.Time}|" +
$"{e.Text};
try
{
Console.WriteLine(message);
}
catch { }
}
}

我试图实现的是在发送最后一条消息后跳过通知或接收数据X毫秒,然后再发送最新收到的消息。我试着让观察者和提供者睡觉,但这只会增加延迟。我想我遗漏了一些东西,任何建议都将不胜感激。

根据我从您的代码中可以看出,您可以用以下代码编写三个类:

var messageTrack = new Subject<MessageEventArgs>();
var query =
from e in messageTrack
where !mMessages.Contains(e.Message)
select $"Message|{e.Time}|{e.Text}";
query.Throttle(TimeSpan.FromMilliseconds(X)).Subscribe(Console.WriteLine);

您永远不需要自己实现IObservable<>IObserver<>。它几乎总是以灾难告终。

上面的代码处理您想要的节流。

最新更新