public void WeakEventHandlerProxy_RaiseEvent_Performance_Within_500x_Non_Reflection_Action() { var testIterations = 10000; var subscriber = new CustomEventSubscriber <EventArgs>(); var proxy = new WeakEventHandlerProxy <EventArgs>(new EventHandler(subscriber.HandleEvent)); var stopwatch = new Stopwatch(); var proxyInvokeStart = stopwatch.ElapsedTicks; stopwatch.Start(); for (var i = 0; i < testIterations; i++) { proxy.RaiseEvent(null, null); } stopwatch.Stop(); var proxyInvokeTicks = stopwatch.ElapsedTicks - proxyInvokeStart; var actionInvokeStart = stopwatch.ElapsedTicks; stopwatch.Start(); for (var i = 0; i < testIterations; i++) { subscriber.HandleEvent(null, null); } stopwatch.Stop(); var actionInvokeTicks = stopwatch.ElapsedTicks - actionInvokeStart; Assert.IsTrue((actionInvokeTicks * 500) >= proxyInvokeTicks, "Invoke through the proxy should be within 100x the ticks to avoid reflection"); }
public async Task WeakEventHandler_Maintains_Weak_Reference_For_Target() { WeakEventHandlerProxy <EventArgs> proxy; { var subscriber = new CustomEventSubscriber <object>(); proxy = new WeakEventHandlerProxy <EventArgs>((Action <object, EventArgs>)subscriber.HandleEvent); Assert.AreEqual(subscriber, proxy.Target, "Proxy Target should be the event subscriber"); subscriber = null; } var waitCount = 0; var maximumWaitCount = 10; while (waitCount < maximumWaitCount) { waitCount++; if (proxy.Target == null) { break; } await Task.Delay(10); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); } Assert.IsNull(proxy.Target, "Proxy Target should be garbage collected, proving it is a weak reference."); Assert.DoesNotThrow(() => proxy.RaiseEvent(null, null), "RaiseEvent should ignore the event if the target has been collected"); }