public void ShouldReceiveDelegateOnDifferentThread() { ManualResetEvent completeEvent = new ManualResetEvent(false); SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); SynchronizationContext calledSyncContext = null; Action <object> action = delegate { calledSyncContext = SynchronizationContext.Current; completeEvent.Set(); }; IDelegateReference actionDelegateReference = new MockDelegateReference() { Target = action }; IDelegateReference filterDelegateReference = new MockDelegateReference() { Target = (Predicate <object>) delegate { return(true); } }; var eventSubscription = new BackgroundEventSubscription <object>(actionDelegateReference, filterDelegateReference); var publishAction = eventSubscription.GetExecutionStrategy(); Assert.NotNull(publishAction); publishAction.Invoke(null); completeEvent.WaitOne(5000); Assert.NotEqual(SynchronizationContext.Current, calledSyncContext); }
public void ShouldReceiveDelegateOnDifferentThread() { int calledThreadId = -1; ManualResetEvent completeEvent = new ManualResetEvent(false); Action <object> action = delegate { calledThreadId = Thread.CurrentThread.ManagedThreadId; completeEvent.Set(); }; IDelegateReference actionDelegateReference = new MockDelegateReference() { Target = action }; IDelegateReference filterDelegateReference = new MockDelegateReference() { Target = (Predicate <object>) delegate { return(true); } }; var eventSubscription = new BackgroundEventSubscription <object>(actionDelegateReference, filterDelegateReference); var publishAction = eventSubscription.GetExecutionStrategy(); Assert.IsNotNull(publishAction); publishAction.Invoke(null); completeEvent.WaitOne(5000, false); Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, calledThreadId); }
public void ShouldReceiveDelegateOnDifferentThread() { ManualResetEvent completeEvent = new ManualResetEvent(false); SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); SynchronizationContext calledSyncContext = null; Action<object> action = delegate { calledSyncContext = SynchronizationContext.Current; completeEvent.Set(); }; IDelegateReference actionDelegateReference = new MockDelegateReference() { Target = action }; IDelegateReference filterDelegateReference = new MockDelegateReference() { Target = (Predicate<object>)delegate { return true; } }; var eventSubscription = new BackgroundEventSubscription<object>(actionDelegateReference, filterDelegateReference, null, EventCommunicatorsRelationship.All); var publishAction = eventSubscription.GetExecutionStrategy(); Assert.NotNull(publishAction); publishAction.Invoke(null); completeEvent.WaitOne(5000); Assert.NotEqual(SynchronizationContext.Current, calledSyncContext); }
public void ShouldReceiveDelegateOnDifferentThreadNonGeneric() { var completeEvent = new ManualResetEvent(false); SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); SynchronizationContext calledSyncContext = null; void action() { calledSyncContext = SynchronizationContext.Current; completeEvent.Set(); } IDelegateReference actionDelegateReference = new MockDelegateReference() { Target = (Action)action }; var eventSubscription = new BackgroundEventSubscription(actionDelegateReference); var publishAction = eventSubscription.GetExecutionStrategy(); Assert.NotNull(publishAction); publishAction.Invoke(null); completeEvent.WaitOne(5000); Assert.NotEqual(SynchronizationContext.Current, calledSyncContext); }
public void ShouldReceiveDelegateOnDifferentThread() { int calledThreadId = -1; ManualResetEvent completeEvent = new ManualResetEvent(false); Action<object> action = delegate { calledThreadId = Thread.CurrentThread.ManagedThreadId; completeEvent.Set(); }; IDelegateReference actionDelegateReference = new MockDelegateReference() { Target = action }; IDelegateReference filterDelegateReference = new MockDelegateReference() { Target = (Predicate<object>)delegate { return true; } }; var eventSubscription = new BackgroundEventSubscription<object>(actionDelegateReference, filterDelegateReference); var publishAction = eventSubscription.GetExecutionStrategy(); Assert.IsNotNull(publishAction); publishAction.Invoke(null); completeEvent.WaitOne(5000, false); Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, calledThreadId); }
/// <summary> /// Subscribes the given delegate reference to the SelectionChanging event. The delegate will be invoked on the specified thread. /// </summary> /// <param name="actionReference"></param> /// <param name="threadOption"></param> /// <returns></returns> public SubscriptionToken Subscribe(IDelegateReference actionReference, ThreadOption threadOption) { IDelegateReference filterReference = new DelegateReference(new Predicate <SelectionBase <T> >(_ => true), true); EventSubscription <SelectionBase <T> > subscription; switch (threadOption) { case ThreadOption.PublisherThread: subscription = new EventSubscription <SelectionBase <T> >(actionReference, filterReference); break; case ThreadOption.BackgroundThread: subscription = new BackgroundEventSubscription <SelectionBase <T> >(actionReference, filterReference); break; case ThreadOption.UIThread: subscription = new DispatcherEventSubscription <SelectionBase <T> >(actionReference, filterReference, UIDispatcher); break; default: throw new NotImplementedException("Thread Option not available."); // Impossible to happen } return(base.InternalSubscribe(subscription)); }
/// <summary> /// Subscribes a delegate to an event. /// </summary> /// <param name="action">The delegate that gets executed when the event is published.</param> /// <param name="threadOption">Specifies on which thread to receive the delegate callback.</param> /// <param name="keepSubscriberReferenceAlive">When <see langword="true"/>, the <seealso cref="CompositeWpfEvent{TPayload}"/> keeps a reference to the subscriber so it does not get garbage collected.</param> /// <param name="filter">Filter to evaluate if the subscriber should receive the event.</param> /// <returns>A <see cref="SubscriptionToken"/> that uniquely identifies the added subscription.</returns> /// <remarks> /// If <paramref name="keepSubscriberReferenceAlive"/> is set to <see langword="false" />, <see cref="CompositeWpfEvent{TPayload}"/> will maintain a <seealso cref="WeakReference"/> to the Target of the supplied <paramref name="action"/> delegate. /// If not using a WeakReference (<paramref name="keepSubscriberReferenceAlive"/> is <see langword="true" />), the user must explicitly call Unsubscribe for the event when disposing the subscriber in order to avoid memory leaks or unexepcted behavior. /// /// The CompositeWpfEvent collection is thread-safe. /// </remarks> public virtual SubscriptionToken Subscribe(Action <TPayload> action, ThreadOption threadOption, bool keepSubscriberReferenceAlive, Predicate <TPayload> filter) { IDelegateReference actionReference = new DelegateReference(action, keepSubscriberReferenceAlive); IDelegateReference filterReference = new DelegateReference(filter, keepSubscriberReferenceAlive); EventSubscription <TPayload> subscription; switch (threadOption) { case ThreadOption.PublisherThread: subscription = new EventSubscription <TPayload>(actionReference, filterReference); break; case ThreadOption.BackgroundThread: subscription = new BackgroundEventSubscription <TPayload>(actionReference, filterReference); break; case ThreadOption.UIThread: subscription = new DispatcherEventSubscription <TPayload>(actionReference, filterReference, UIDispatcher); break; default: subscription = new EventSubscription <TPayload>(actionReference, filterReference); break; } return(base.InternalSubscribe(subscription)); }
/// <summary> /// Subscribes a delegate to an event. /// </summary> /// <param name="action">The delegate that gets executed when the event is published.</param> /// <param name="threadOption">Specifies on which thread to receive the delegate callback.</param> /// <param name="keepSubscriberReferenceAlive">When <see langword="true"/>, the <see cref="PubSubEvent"/> keeps a reference to the subscriber so it does not get garbage collected.</param> /// <returns>A <see cref="SubscriptionToken"/> that uniquely identifies the added subscription.</returns> /// <remarks> /// If <paramref name="keepSubscriberReferenceAlive"/> is set to <see langword="false" />, <see cref="PubSubEvent"/> will maintain a <see cref="WeakReference"/> to the Target of the supplied <paramref name="action"/> delegate. /// If not using a WeakReference (<paramref name="keepSubscriberReferenceAlive"/> is <see langword="true" />), the user must explicitly call Unsubscribe for the event when disposing the subscriber in order to avoid memory leaks or unexpected behavior. /// <para/> /// The PubSubEvent collection is thread-safe. /// </remarks> public virtual SubscriptionToken Subscribe(Action action, ThreadOption threadOption, bool keepSubscriberReferenceAlive) { IDelegateReference actionReference = new DelegateReference(action, keepSubscriberReferenceAlive); EventSubscription subscription; switch (threadOption) { case ThreadOption.PublisherThread: subscription = new EventSubscription(actionReference); break; case ThreadOption.BackgroundThread: subscription = new BackgroundEventSubscription(actionReference); break; case ThreadOption.UIThread: if (SynchronizationContext == null) { throw new InvalidOperationException(Resources.EventAggregatorNotConstructedOnUIThread); } subscription = new DispatcherEventSubscription(actionReference, SynchronizationContext); break; default: subscription = new EventSubscription(actionReference); break; } return(InternalSubscribe(subscription)); }
/// <summary> /// Subscribes a delegate to an event. /// </summary> /// <param name="action">The delegate that gets executed when the event is published.</param> /// <param name="threadOption">Specifies on which thread to receive the delegate callback.</param> /// <param name="keepSubscriberReferenceAlive">When <see langword="true"/>, the <seealso cref="CompositeSynchronizationContextEvent{TPayload}"/> keeps a reference to the subscriber so it does not get garbage collected.</param> /// <param name="filter">Filter to evaluate if the subscriber should receive the event.</param> /// <returns>A <see cref="SubscriptionToken"/> that uniquely identifies the added subscription.</returns> /// <remarks> /// If <paramref name="keepSubscriberReferenceAlive"/> is set to <see langword="false" />, <see cref="CompositeSynchronizationContextEvent{TPayload}"/> will maintain a <seealso cref="WeakReference"/> to the Target of the supplied <paramref name="action"/> delegate. /// If not using a WeakReference (<paramref name="keepSubscriberReferenceAlive"/> is <see langword="true" />), the user must explicitly call Unsubscribe for the event when disposing the subscriber in order to avoid memory leaks or unexepcted behavior. /// /// The CompositeSynchronizationContextEvent collection is thread-safe. /// </remarks> public virtual SubscriptionToken Subscribe(Action <TPayload> action, ThreadOption threadOption, bool keepSubscriberReferenceAlive, Predicate <TPayload> filter) { IDelegateReference actionReference = new DelegateReference(action, keepSubscriberReferenceAlive); IDelegateReference filterReference = new DelegateReference(filter, keepSubscriberReferenceAlive); EventSubscription <TPayload> subscription; switch (threadOption) { case ThreadOption.PublisherThread: subscription = new EventSubscription <TPayload>(actionReference, filterReference); break; case ThreadOption.BackgroundThread: subscription = new BackgroundEventSubscription <TPayload>(actionReference, filterReference); break; case ThreadOption.SubscriberAffinityThread: subscription = new CompositeEventSubscription <TPayload>(actionReference, filterReference, SynchronizationContext.Current); break; default: subscription = new EventSubscription <TPayload>(actionReference, filterReference); break; } return(base.InternalSubscribe(subscription)); }
/// <summary> /// Subscribe a <see cref="Action"/> to the <see cref="PubSubEvent"/> /// </summary> /// <param name="action">The <see cref="Action"/> that gets executed when the event is published</param> /// <param name="threadOption">Specifies on which thread the received delegate is executed</param> /// <param name="keepSubscriberReferenceAlive">If set to <see langword="true"/> the <see cref="PubSubEvent"/> will hold a strong reference to the action, otherwise a weak reference will be kept</param> /// <returns>Returns <see cref="SubscriptionToken"/> that uniquely identifies the subscription</returns> public virtual SubscriptionToken Subscribe(Action action, ThreadOption threadOption, bool keepSubscriberReferenceAlive) { var actionReference = new DelegateReference(action, keepSubscriberReferenceAlive); EventSubscription subscription; switch (threadOption) { case ThreadOption.BackgroundThread: subscription = new BackgroundEventSubscription(actionReference); break; case ThreadOption.PublisherThread: subscription = new EventSubscription(actionReference); break; case ThreadOption.UIThread: if (SynchronizationContext == null) { throw new ArgumentNullException(nameof(SynchronizationContext)); } subscription = new DispatcherEventSubscription(actionReference, SynchronizationContext); break; default: subscription = new EventSubscription(actionReference); break; } return(InternalSubscribe(subscription)); }
/// <summary> /// Subscribes a delegate to an event. /// </summary> /// <param name="action">The delegate that gets executed when the event is published.</param> /// <param name="threadOption">Specifies on which thread to receive the delegate callback.</param> /// <param name="keepSubscriberReferenceAlive">When <see langword="true"/>, the <see cref="PubSubEvent{TPayload}"/> keeps a reference to the subscriber so it does not get garbage collected.</param> /// <param name="filter">Filter to evaluate if the subscriber should receive the event.</param> /// <returns>A <see cref="SubscriptionToken"/> that uniquely identifies the added subscription.</returns> /// <remarks> /// If <paramref name="keepSubscriberReferenceAlive"/> is set to <see langword="false" />, <see cref="PubSubEvent{TPayload}"/> will maintain a <see cref="WeakReference"/> to the Target of the supplied <paramref name="action"/> delegate. /// If not using a WeakReference (<paramref name="keepSubscriberReferenceAlive"/> is <see langword="true" />), the user must explicitly call Unsubscribe for the event when disposing the subscriber in order to avoid memory leaks or unexpected behavior. /// /// The PubSubEvent collection is thread-safe. /// </remarks> public virtual SubscriptionToken Subscribe(Action <TPayload> action, ThreadOption threadOption, bool keepSubscriberReferenceAlive, Predicate <TPayload> filter) { IDelegateReference actionReference = new DelegateReference(action, keepSubscriberReferenceAlive); IDelegateReference filterReference; if (filter != null) { filterReference = new DelegateReference(filter, keepSubscriberReferenceAlive); } else { filterReference = new DelegateReference(new Predicate <TPayload>(delegate { return(true); }), true); } EventSubscription <TPayload> subscription; switch (threadOption) { case ThreadOption.PublisherThread: subscription = new EventSubscription <TPayload>(actionReference, filterReference); break; case ThreadOption.BackgroundThread: subscription = new BackgroundEventSubscription <TPayload>(actionReference, filterReference); break; case ThreadOption.UIThread: if (SynchronizationContext == null) { throw new InvalidOperationException("Resources.EventAggregatorNotConstructedOnUIThread"); } subscription = new DispatcherEventSubscription <TPayload>(actionReference, filterReference, SynchronizationContext); break; default: subscription = new EventSubscription <TPayload>(actionReference, filterReference); break; } return(base.InternalSubscribe(subscription)); }
/// <summary> /// Subscribes a delegate to an event. /// </summary> /// <param name="action">The delegate that gets executed when the event is published.</param> /// <param name="threadOption">Specifies on which thread to receive the delegate callback.</param> /// <param name="keepSubscriberReferenceAlive">When <see langword="true"/>, the <see cref="CompositePresentationEvent{TPayload}"/> keeps a reference to the subscriber so it does not get garbage collected.</param> /// <param name="filter">Filter to evaluate if the subscriber should receive the event.</param> /// <returns>A <see cref="SubscriptionToken"/> that uniquely identifies the added subscription.</returns> /// <remarks> /// If <paramref name="keepSubscriberReferenceAlive"/> is set to <see langword="false" />, <see cref="CompositePresentationEvent{TPayload}"/> will maintain a <see cref="WeakReference"/> to the Target of the supplied <paramref name="action"/> delegate. /// If not using a WeakReference (<paramref name="keepSubscriberReferenceAlive"/> is <see langword="true" />), the user must explicitly call Unsubscribe for the event when disposing the subscriber in order to avoid memory leaks or unexepcted behavior. /// /// The CompositePresentationEvent collection is thread-safe. /// </remarks> public virtual SubscriptionToken Subscribe(Action <TPayload> action, ThreadOption threadOption, bool keepSubscriberReferenceAlive, Predicate <TPayload> filter) { IDelegateReference actionReference = new DelegateReference(action, keepSubscriberReferenceAlive); IDelegateReference filterReference; if (filter != null) { filterReference = new DelegateReference(filter, keepSubscriberReferenceAlive); } else { filterReference = new DelegateReference(new Predicate <TPayload>(delegate { return(true); }), true); } EventSubscription <TPayload> subscription; switch (threadOption) { case ThreadOption.PublisherThread: subscription = new EventSubscription <TPayload>(actionReference, filterReference); break; case ThreadOption.BackgroundThread: subscription = new BackgroundEventSubscription <TPayload>(actionReference, filterReference); break; case ThreadOption.UIThread: subscription = new PrismCommonLib.Composition.Events.DispatcherEventSubscription <TPayload>(actionReference, filterReference, UIDispatcher); break; default: subscription = new EventSubscription <TPayload>(actionReference, filterReference); break; } return(base.InternalSubscribe(subscription)); }