ÖNEMLİ: sonuçlarınızın açıklaması ve biraz daha ayrıntılı, nesnelerin/genellikle olaylar dizisi Gruba gerekRx operatörü
benim cevaba da bir göz atın ve filtrelemek için lütfen çoğaltılır, bunları bir TimeSpan aralığı ile tamponlar. Ben mermer diyagramların çeşit daha iyi anlatmaya çalışacağım:
X-X-X-X-X-Y-Y-Y-Z-Z-Z-Z-X-X-Y-Z-Z
üretecektir X, Y ve Z farklı olay türleri vardır ve '---' aralık anlamına
X---Y---Z---X---Y---Z
. Ayrıca, yapardım da ortak bir temel sınıf çünkü her türlü geçerli bir anahtar özelliğiyle farklı nasıl bir:
X, Y, Z : A
ve A bir özellik Anahtarı içerir. Xa anlamı X.Key = bir gösterim kullanılarak, son bir örnek olacaktır:
X.a-X.b-X.a-Y.b-Y.c-Z.a-Z.a-Z.c-Z.b-Z.c
X.a-X.b---Y.b-Y.c-Z.a-Z.c-Z.b
kimse beni birlikte gerekli Linq operatörleri (muhtemelen DistinctUntilChanged ve Tampon) koyarak yardım edebilir üretecektir Bu davranışa ulaşmak? Teşekkür
GÜNCELLEME 18.08.12: istendiği gibi
, ben daha iyi bir açıklama vermeye çalışıyoruz. Olayları bir web servisine toplayıp gönderen cihazlarımız var. Bu cihazların eski bir mantığı vardır (ve geriye dönük uyumluluk nedeniyle bunu değiştiremeyiz) ve bir onay aldıkça sürekli bir etkinlik gönderirler; onayladıktan sonra, sıradaki olayları sıraya gönderir, vb. Olaylar, birimin ağ adresini ve her aygıt için sıradaki olayları ayıran bazı diğer özellikleri içerir. Bir olay şöyle görünür:
class Event
{
public string NetworkAddress { get; }
public string EventCode { get; }
public string AdditionalAttribute { get; }
}
gol (biz toplu olarak bunu yapmak istemiyorum bu yüzden) veritabanında bilgi, seçkin olaylar tüm cihazlardan alınan her 5 saniyede işleme depolama olmasıdır ve ack'i cihaza yollamak. Muhtemelen basit bir kombinasyon olduğunu düşünüyorum
Device 'a' : -[a1]-[a1]-[a1]----------------[a2]-[a2]-[a2]-[a3]-[a3]-[a3]-...
Device 'b' : ------[b1]-[b1]-[b2]-[b2]-[b2]------[b3]-[b3]-[b4]-[b4]-[b4]-...
Time : ------------[1s]-----------[2s]------------[3s]------------[4s]-
DB/acks (rx output) : ------------[P1]-----------[P2]------------[P3]------------[P4]-
P1: Server stores and acknowledges [a1] and [b1]
P2: " " " " [b2]
P3: " " " " [a2] and [b3]
P4: " " " " [a3] and [b4]
Sonunda:
Device 'a':
Event 1 (a1): NetworkAddress = '1', EventCode = A, AdditionalAttribute = 'x'
Event 2 (a2): NetworkAddress = '1', EventCode = A, AdditionalAttribute = 'y'
Event 3 (a3): NetworkAddress = '1', EventCode = B, AdditionalAttribute = 'x'
Device 'b':
Event 1 (b1): NetworkAddress = '2', EventCode = A, AdditionalAttribute = 'y'
Event 2 (b2): NetworkAddress = '2', EventCode = B, AdditionalAttribute = 'x'
Event 3 (b3): NetworkAddress = '2', EventCode = B, AdditionalAttribute = 'y'
Event 4 (b4): NetworkAddress = '2', EventCode = C, AdditionalAttribute = 'x'
Pn are the operations done by our server, explained later
Olası mermer diyagramı (giriş akışları + çıkış akımı): tek iki cihaz ve bazı olaylarla bir örnek yapalım temel operatörler, ama ben Rx için yeniyim ve biraz çıkışım var, çünkü aynı çıktı akışını elde etmek için çok sayıda operatör (veya operatör kombinasyonları) var gibi görünüyor.
Güncelleme 19.08.12: Bu kod, bir sunucu üzerinde çalışır ve ben deneklerin davranışı hakkında emin değilim ... bellek sızıntılarını olmadan günlerce çalışması gerektiğini
unutmayın.Şu anda, her bir olay için, bir sorguda (konuların kullanımı konusunda yanılmıyorsam) bir Konunun OnNext'ini sorgulayabilmem için bir hizmet üzerinde bir basma işlemi çağırıyorum.Güncelleme 20.08.12:
doğrulama testi dahil Güncel uygulanması; Bu ne denedim olduğunu ve @yamen
public interface IEventService
{
// Persists the events
void Add(IEnumerable<Event> events);
}
public class Event
{
public string Description { get; set; }
}
/// <summary>
/// Implements the logic to handle events.
/// </summary>
public class EventManager : IDisposable
{
private static readonly TimeSpan EventHandlingPeriod = TimeSpan.FromSeconds(5);
private readonly Subject<EventMessage> subject = new Subject<EventMessage>();
private readonly IDisposable subscription;
private readonly object locker = new object();
private readonly IEventService eventService;
/// <summary>
/// Initializes a new instance of the <see cref="EventManager"/> class.
/// </summary>
/// <param name="scheduler">The scheduler.</param>
public EventManager(IEventService eventService, IScheduler scheduler)
{
this.eventService = eventService;
this.subscription = this.CreateQuery(scheduler);
}
/// <summary>
/// Pushes the event.
/// </summary>
/// <param name="eventMessage">The event message.</param>
public void PushEvent(EventMessage eventMessage)
{
Contract.Requires(eventMessage != null);
this.subject.OnNext(eventMessage);
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
/// <filterpriority>2</filterpriority>
public void Dispose()
{
this.Dispose(true);
}
private void Dispose(bool disposing)
{
if (disposing)
{
// Dispose unmanaged resources
}
this.subject.Dispose();
this.subscription.Dispose();
}
private IDisposable CreateQuery(IScheduler scheduler)
{
var buffered = this.subject
.DistinctUntilChanged(new EventComparer())
.Buffer(EventHandlingPeriod, scheduler);
var query = buffered
.Subscribe(this.HandleEvents);
return query;
}
private void HandleEvents(IList<EventMessage> eventMessages)
{
Contract.Requires(eventMessages != null);
var events = eventMessages.Select(this.SelectEvent);
this.eventService.Add(events);
}
private Event SelectEvent(EventMessage message)
{
return new Event { Description = "evaluated description" };
}
private class EventComparer : IEqualityComparer<EventMessage>
{
public bool Equals(EventMessage x, EventMessage y)
{
return x.NetworkAddress == y.NetworkAddress && x.EventCode == y.EventCode && x.Attribute == y.Attribute;
}
public int GetHashCode(EventMessage obj)
{
var s = string.Concat(obj.NetworkAddress + "_" + obj.EventCode + "_" + obj.Attribute);
return s.GetHashCode();
}
}
}
public class EventMessage
{
public string NetworkAddress { get; set; }
public byte EventCode { get; set; }
public byte Attribute { get; set; }
// Other properties
}
Ve testin önerdiği aynı görünüyor:
public void PushEventTest()
{
const string Address1 = "A:2.1.1";
const string Address2 = "A:2.1.2";
var eventServiceMock = new Mock<IEventService>();
var scheduler = new TestScheduler();
var target = new EventManager(eventServiceMock.Object, scheduler);
var eventMessageA1 = new EventMessage { NetworkAddress = Address1, EventCode = 1, Attribute = 4 };
var eventMessageB1 = new EventMessage { NetworkAddress = Address2, EventCode = 1, Attribute = 5 };
var eventMessageA2 = new EventMessage { NetworkAddress = Address1, EventCode = 1, Attribute = 4 };
scheduler.Schedule(() => target.PushEvent(eventMessageA1));
scheduler.Schedule(TimeSpan.FromSeconds(1),() => target.PushEvent(eventMessageB1));
scheduler.Schedule(TimeSpan.FromSeconds(2),() => target.PushEvent(eventMessageA1));
scheduler.AdvanceTo(TimeSpan.FromSeconds(6).Ticks);
eventServiceMock.Verify(s => s.Add(It.Is<List<Event>>(list => list.Count == 2)), Times.Once());
scheduler.Schedule(TimeSpan.FromSeconds(3),() => target.PushEvent(eventMessageB1));
scheduler.AdvanceTo(TimeSpan.FromSeconds(11).Ticks);
eventServiceMock.Verify(s => s.Add(It.Is<List<Event>>(list => list.Count == 1)), Times.Once());
}
Ayrıca, ben yazılım olmadan günlerce çalıştırabilir gerçekten önemli olduğunu tekrar sözler sorunlar, binlerce mesajla ilgileniyor. Netleştirmek için: test mevcut uygulama ile geçmiyor.
sorunuzun 'X.a-X.b --- Y.b-Y.c-Z.a-Z.c-Z.b' tek' --- 'aralığını gösterir final dizisi. Bu doğru mu, yoksa aralık her bir değer arasında mı olmalı? – Enigmativity
Eğer mermer diyagramları bir kaynak olarak sağladıysanız ve birbirinin altında 'ölçeklemek' hedefine ulaşırsanız ya da size yardımcı olacak 'gerçek' bir örnek sağlamanız yararlı olacaktır. – yamen
Yakalama Enigmativity için teşekkürler, ben çıkış @yamen sabitleyeceğim Daha fazla ayrıntı ekleyeceğim – fra