// © 2005 IDesign Inc. All rights reserved //Questions? Comments? go to //http://www.idesign.net using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Threading; namespace DelftTools.Utils.Threading { /// /// From .net components by O'Reilly /// public static class EventsHelper { private delegate void AsyncFire(Delegate del, object[] args); [MethodImpl(MethodImplOptions.NoInlining)] public static void UnsafeFire(Delegate del, params object[] args) { if (args.Length > 7) { Trace.TraceWarning("Too many parameters. Consider a structure to enable the use of the type-safe versions"); } if (del == null) { return; } Delegate[] delegates = del.GetInvocationList(); foreach (Delegate sink in delegates) { InvokeDelegate(sink, args); } } [MethodImpl(MethodImplOptions.NoInlining)] public static void UnsafeFireInParallel(Delegate del, params object[] args) { if (args.Length > 7) { Trace.TraceWarning("Too many parameters. Consider a structure to enable the use of the type-safe versions"); } if (del == null) { return; } Delegate[] delegates = del.GetInvocationList(); List calls = new List(delegates.Length); AsyncFire asyncFire = InvokeDelegate; foreach (Delegate sink in delegates) { IAsyncResult asyncResult = asyncFire.BeginInvoke(sink, args, null, null); calls.Add(asyncResult.AsyncWaitHandle); } WaitHandle[] handles = calls.ToArray(); WaitHandle.WaitAll(handles); Action close = delegate(WaitHandle handle) { handle.Close(); }; Array.ForEach(handles, close); } [MethodImpl(MethodImplOptions.NoInlining)] public static void UnsafeFireAsync(Delegate del, params object[] args) { if (args.Length > 7) { Trace.TraceWarning("Too many parameters. Consider a structure to enable the use of the type-safe versions"); } if (del == null) { return; } Delegate[] delegates = del.GetInvocationList(); AsyncFire asyncFire = InvokeDelegate; AsyncCallback cleanUp = delegate(IAsyncResult asyncResult) { asyncResult.AsyncWaitHandle.Close(); }; foreach (Delegate sink in delegates) { asyncFire.BeginInvoke(sink, args, cleanUp, null); } } public static void Fire(EventHandler del, object sender, EventArgs e) where T : EventArgs { UnsafeFire(del, sender, e); } public static void Fire(EventHandler del, object sender, EventArgs e) { UnsafeFire(del, sender, e); } public static void Fire(EventHandler del, object sender, T t) where T : EventArgs { UnsafeFire(del, sender, t); } public static void Fire(GenericEventHandler del) { UnsafeFire(del); } public static void Fire(GenericEventHandler del, T t) { UnsafeFire(del, t); } public static void Fire(GenericEventHandler del, T t, U u) { UnsafeFire(del, t, u); } public static void Fire(GenericEventHandler del, T t, U u, V v) { UnsafeFire(del, t, u, v); } public static void Fire(GenericEventHandler del, T t, U u, V v, W w) { UnsafeFire(del, t, u, v, w); } public static void Fire(GenericEventHandler del, T t, U u, V v, W w, X x) { UnsafeFire(del, t, u, v, w, x); } public static void Fire(GenericEventHandler del, T t, U u, V v, W w, X x, Y y) { UnsafeFire(del, t, u, v, w, x, y); } public static void Fire(GenericEventHandler del, T t, U u, V v, W w, X x, Y y, Z z) { UnsafeFire(del, t, u, v, w, x, y, z); } public static void FireInParallel(EventHandler del, object sender, EventArgs e) { UnsafeFireInParallel(del, sender, e); } public static void FireInParallel(EventHandler del, object sender, T t) where T : EventArgs { UnsafeFireInParallel(del, sender, t); } public static void FireInParallel(GenericEventHandler del) { UnsafeFireInParallel(del); } public static void FireInParallel(GenericEventHandler del, T t) { UnsafeFireInParallel(del, t); } public static void FireInParallel(GenericEventHandler del, T t, U u) { UnsafeFireInParallel(del, t, u); } public static void FireInParallel(GenericEventHandler del, T t, U u, V v) { UnsafeFireInParallel(del, t, u, v); } public static void FireInParallel(GenericEventHandler del, T t, U u, V v, W w) { UnsafeFireInParallel(del, t, u, v, w); } public static void FireInParallel(GenericEventHandler del, T t, U u, V v, W w, X x) { UnsafeFireInParallel(del, t, u, v, w, x); } public static void FireInParallel(GenericEventHandler del, T t, U u, V v, W w, X x, Y y) { UnsafeFireInParallel(del, t, u, v, w, x, y); } public static void FireInParallel(GenericEventHandler del, T t, U u, V v, W w, X x, Y y, Z z) { UnsafeFireInParallel(del, t, u, v, w, x, y, z); } public static void FireAsync(EventHandler del, object sender, EventArgs e) { UnsafeFireAsync(del, sender, e); } public static void FireAsync(EventHandler del, object sender, T t) where T : EventArgs { UnsafeFireAsync(del, sender, t); } public static void FireAsync(GenericEventHandler del) { UnsafeFireAsync(del); } public static void FireAsync(GenericEventHandler del, T t) { UnsafeFireAsync(del, t); } public static void FireAsync(GenericEventHandler del, T t, U u) { UnsafeFireAsync(del, t, u); } public static void FireAsync(GenericEventHandler del, T t, U u, V v) { UnsafeFireAsync(del, t, u, v); } public static void FireAsync(GenericEventHandler del, T t, U u, V v, W w) { UnsafeFireAsync(del, t, u, v, w); } public static void FireAsync(GenericEventHandler del, T t, U u, V v, W w, X x) { UnsafeFireAsync(del, t, u, v, w, x); } public static void FireAsync(GenericEventHandler del, T t, U u, V v, W w, X x, Y y) { UnsafeFireAsync(del, t, u, v, w, x, y); } public static void FireAsync(GenericEventHandler del, T t, U u, V v, W w, X x, Y y, Z z) { UnsafeFireAsync(del, t, u, v, w, x, y, z); } private static void InvokeDelegate(Delegate del, object[] args) { ISynchronizeInvoke synchronizer = del.Target as ISynchronizeInvoke; if (synchronizer != null) //Requires thread affinity { if (synchronizer.InvokeRequired) { synchronizer.Invoke(del, args); return; } } //Not requiring thread afinity or invoke is not required del.DynamicInvoke(args); } } }