public static void SetTimer(Action d, object key, ReenteranceMode rMode, TimeSpan initial, TimeSpan frequency) { TimerEx t = null; lock (timers) { if (timers.ContainsKey(key)) { t = timers[key]; if (d == null) { t.Close(); timers.Remove(key); } else { t.d = d; t.Timer.Change(initial, frequency); t.Mode = rMode; } } else { if (d != null) { t = new TimerEx(d, rMode, initial, frequency); timers.Add(key, t); } } } }
internal AsyncRes(object state, Delegate d, string key, ReenteranceMode rMode) { this.state = state; this.asyncDelegate = d; this.key = key; this.RMode = rMode; }
private void TimerMethod(object o) { if (d == null) { Console.WriteLine("Empty Delegate, disposing timer."); if (Timer != null) { Timer.Dispose(); } return; } ReenteranceMode m = Mode; if (m == ReenteranceMode.Bypass) { if (!Monitor.TryEnter(lck)) { return; } } else if (m == ReenteranceMode.Stack) { Monitor.Enter(lck); } try { //Do stuff d(); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("Async Timer Exception:" + ex); } finally { if (m != ReenteranceMode.Allow) { Monitor.Exit(lck); } } }
/// <summary> /// Fires off your delegate asyncronously, using the threadpool or a full managed thread if needed. /// </summary> /// <param name="d">A void delegate - can be cast to (Dlg) from an anonymous delgate or method: Async.Do((Dlg)MyVoidMethod);</param> /// <param name="rMode">If true, will make sure no other instances are running your method.</param> /// <returns>AsyncRes with all kind o' goodies for waiting, result values, etc.</returns> public static AsyncRes Do(Dlg d, ReenteranceMode rMode) { return Do(null, d, false, null, true, rMode, null, true); }
/// <summary> /// Fires off your delegate asyncronously, using the threadpool or a full managed thread if needed. /// </summary> /// <param name="d">A void delegate - can be cast to (Action) from an anonymous delgate or method: Async.Do((Action)MyVoidMethod);</param> /// <param name="state">A user object that can be tracked through the returned result</param> /// <param name="async">Whether to run async, or try on current thread if invoke is not required.</param> /// <param name="rMode">If true, will make sure no other instances are running your method.</param> /// <param name="dispatcher">A dispatcher to Invoke upon GUI thread of, if needed. Null if unused.</param> /// <returns>AsyncRes with all kind of goodies for waiting, result values, etc.</returns> public static AsyncRes UI(Action d, Dispatcher dispatcher, object state, bool isAsync, ReenteranceMode rMode) { return(Do(null, d, false, state, false, rMode, isAsync, dispatcher)); }
/// <summary> /// Fires off your delegate asyncronously, using the threadpool or a full managed thread if needed. /// </summary> /// <param name="d">A delegate with a return value of some sort - can be cast to (DlgR) from an anonymous delgate with a return: Async.Do((DlgR)MyMethod);</param> /// <param name="state">A user object that can be tracked through the returned result</param> /// <param name="tryThreadPool">True to use the TP, otherwise just go to a ful lthread - good for long running tasks.</param> /// <param name="rMode">If true, will make sure no other instances are running your method.</param> /// <param name="getRetVal">If true, and the method/delgete returns something, it is included in the AsyncRes returned (after the method completes)</param> /// <returns>AsyncRes with all kind o' goodies for waiting, resturn and result values, etc.</returns> public static AsyncRes Do(DlgR d, bool getRetVal, object state, bool tryThreadPool, ReenteranceMode rMode) { return(Do(d, null, getRetVal, state, tryThreadPool, rMode)); }
/// <summary> /// Fires off your delegate asyncronously, using the threadpool or a full managed thread if needed. /// </summary> /// <param name="d">A delegate with a return value of some sort - can be cast to (DlgR) from an anonymous delgate with a return: Async.Do((DlgR)MyMethod);</param> /// <param name="rMode">If true, will make sure no other instances are running your method.</param> /// <param name="getRetVal">If true, and the method/delgete returns something, it is included in the AsyncRes returned (after the method completes)</param> /// <returns>AsyncRes with all kind o' goodies for waiting, resturn and result values, etc.</returns> public static AsyncRes Do(DlgR d, bool getRetVal, ReenteranceMode rMode) { return(Do(d, null, getRetVal, null, true, rMode)); }
/// <summary> /// Fires off your delegate asyncronously, using the threadpool or a full managed thread if needed. /// </summary> /// <param name="d">A void delegate - can be cast to (Dlg) from an anonymous delgate.</param> /// <param name="dr">A delegate with a return value of some sort - can be cast to (DlgR) from an anonymous delgate with a return.</param> /// <param name="state">A user object that can be tracked through the returned result</param> /// <param name="getRetVal">If true, and the method/delgete returns something, it is included in the AsyncRes returned (after the method completes)</param> /// <param name="tryThreadPool">True to use the TP, otherwise just go to a ful lthread - good for long running tasks.</param> /// <param name="rMode">If true, will make sure no other instances are running your method.</param> /// <returns>AsyncRes with all kind o' goodies for waiting, result values, etc.</returns> private static AsyncRes Do(DlgR dr, Dlg d, bool getRetVal, object state, bool tryThreadPool, ReenteranceMode rMode) { //get a generic MethodInfo for checks.. MethodInfo mi = ((dr != null) ? dr.Method : d.Method); //make a unique key for output usage string key = string.Format("{0}{1}{2}{3}", ((getRetVal) ? "<-" : ""), mi.DeclaringType, ((mi.IsStatic) ? ":" : "."), mi.Name); //our custom return value, holds our delegate, state, key, etc. AsyncRes res = new AsyncRes(state, ((dr != null) ? (Delegate)dr : (Delegate)d), key, rMode); //Create a delegate wrapper for what we will actually invoke.. Dlg dlg = (Dlg) delegate { if (!BeforeInvoke(res)) { return; //checks for reentrance issues and sets us up } try { if (res.IsCompleted) { return; } if (dr != null) { res.retVal = dr(); //use this one if theres a return } else { d(); //otherwise the simpler dlg } } catch (Exception ex) { //we never want a rogue exception on a random thread, it can't bubble up anywhere // logger.Error("Async Exception:" + ex); } finally { FinishInvoke(res); //this will fire our callback if they used it, and clean up } }; if (tryThreadPool) //we are going to use the .NET threadpool { try { //get some stats - much better than trying and silently failing or throwing an expensive exception int minThreads, minIO, threads, ioThreads, totalThreads, totalIO; ThreadPool.GetMinThreads(out minThreads, out minIO); ThreadPool.GetAvailableThreads(out threads, out ioThreads); ThreadPool.GetMaxThreads(out totalThreads, out totalIO); //check for at least our thread plus one more in ThreadPool if (threads > minThreads) { //this is what actually fires this task off.. bool result = ThreadPool.QueueUserWorkItem((WaitCallback) delegate { dlg(); }); if (result) { res.result = AsyncAction.ThreadPool; //this means success in queueing and running the item return(res); } else { //according to docs, this "won't ever happen" - exception instead, but just for kicks. //logger.Error("Failed to queue in threadpool, Method: " + key); } } else { Console.WriteLine(String.Format("Insufficient idle threadpool threads: {0} of {1} - min {2}, Method: {3}", threads, totalThreads, minThreads, key)); } } catch (Exception ex) { // logger.Error("Failed to queue in threadpool: " + ex.Message, ex); } } //if we got this far, then something up there failed, or they wanted a dedicated thread Thread t = new Thread((ThreadStart) delegate { dlg(); }); t.IsBackground = true; //this or threadpriority are candidates for additional settings t.Name = "Async_" + key; res.result = AsyncAction.Thread; t.Start(); return(res); }
/// <summary> /// Fires off your delegate, carefully using the correct UI thread /// </summary> /// <param name="d">A delegate with a return value of some sort - can be cast to (DlgR) from an anonymous delgate with a return: Async.Do((DlgR)MyMethod);</param> /// <param name="state">A user object that can be tracked through the returned result</param> /// <param name="async">Whether to run async, or try on current thread if invoke is not required.</param> /// <param name="getRetVal">If true, and the method/delgete returns something, it is included in the AsyncRes returned (after the method completes)</param> /// <param name="rMode">If true, will make sure no other instances are running your method.</param> /// <param name="c">A control to Invoke upon GUI thread of, if needed. Null if unused.</param> /// <returns>AsyncRes with all kind o' goodies for waiting, result values, etc.</returns> public static AsyncRes UI(DlgR d, bool getRetVal, Control c, object state, bool async, ReenteranceMode rMode) { return Do(d, null, getRetVal, state, false, rMode, c, async); }
/// <summary> /// Fires off your delegate, carefully using the correct UI thread /// </summary> /// <param name="d">A delegate with a return value of some sort - can be cast to (DlgR) from an anonymous delgate with a return: Async.Do((DlgR)MyMethod);</param> /// <param name="state">A user object that can be tracked through the returned result</param> /// <param name="async">Whether to run async, or try on current thread if invoke is not required.</param> /// <param name="getRetVal">If true, and the method/delgete returns something, it is included in the AsyncRes returned (after the method completes)</param> /// <param name="rMode">If true, will make sure no other instances are running your method.</param> /// <param name="c">A control to Invoke upon GUI thread of, if needed. Null if unused.</param> /// <returns>AsyncRes with all kind o' goodies for waiting, result values, etc.</returns> public static AsyncRes UI(DlgR d, bool getRetVal, Control c, object state, bool async, ReenteranceMode rMode) { return(Do(d, null, getRetVal, state, false, rMode, c, async)); }
/// <summary> /// Fires off your delegate asyncronously, using the threadpool or a full managed thread if needed. /// </summary> /// <param name="d">A delegate with a return value of some sort - can be cast to (Func<object>) from an anonymous delgate with a return: Async.Do((Func<object>)MyMethod);</param> /// <param name="rMode">If true, will make sure no other instances are running your method.</param> /// <param name="getRetVal">If true, and the method/delgete returns something, it is included in the AsyncRes returned (after the method completes)</param> /// <returns>AsyncRes with all kind of goodies for waiting, resturn and result values, etc.</returns> public static AsyncRes Do(Func <object> d, bool getRetVal, ReenteranceMode rMode) { return(Do(d, null, getRetVal, null, true, rMode, true, null)); }
public TimerEx(Action d, ReenteranceMode rMode, TimeSpan initial, TimeSpan frequency) { this.d = d; this.Mode = rMode; Timer = new System.Threading.Timer(TimerMethod, null, initial, frequency); }
/// <summary> /// Fires off your delegate asyncronously, using the threadpool or a full managed thread if needed. /// </summary> /// <param name="d">A delegate with a return value of some sort - can be cast to (Func<object>) from an anonymous delgate with a return: Async.Do((Func<object>)MyMethod);</param> /// <param name="state">A user object that can be tracked through the returned result</param> /// <param name="async">Whether to run async, or try on current thread if invoke is not required.</param> /// <param name="getRetVal">If true, and the method/delgete returns something, it is included in the AsyncRes returned (after the method completes)</param> /// <param name="rMode">If true, will make sure no other instances are running your method.</param> /// <param name="dispatcher">A dispatcher to Invoke upon GUI thread of, if needed. Null if unused.</param> /// <returns>AsyncRes with all kind of goodies for waiting, result values, etc.</returns> public static AsyncRes UI(Func <object> d, bool getRetVal, Dispatcher dispatcher, object state, bool isAsync, ReenteranceMode rMode) { return(Do(d, null, getRetVal, state, false, rMode, isAsync, dispatcher)); }
/// <summary> /// Fires off your delegate asyncronously, using the threadpool or a full managed thread if needed. /// </summary> /// <param name="d">A delegate with a return value of some sort - can be cast to (DlgR) from an anonymous delgate with a return: Async.Do((DlgR)MyMethod);</param> /// <param name="state">A user object that can be tracked through the returned result</param> /// <param name="tryThreadPool">True to use the TP, otherwise just go to a ful lthread - good for long running tasks.</param> /// <param name="rMode">If true, will make sure no other instances are running your method.</param> /// <param name="getRetVal">If true, and the method/delgete returns something, it is included in the AsyncRes returned (after the method completes)</param> /// <returns>AsyncRes with all kind o' goodies for waiting, resturn and result values, etc.</returns> public static AsyncRes Do(DlgR d, bool getRetVal, object state, bool tryThreadPool, ReenteranceMode rMode) { return Do(d, null, getRetVal, state, tryThreadPool, rMode, null, true); }
/// <summary> /// Fires off your delegate asyncronously, using the threadpool or a full managed thread if needed. /// </summary> /// <param name="d">A void delegate - can be cast to (Dlg) from an anonymous delgate or method: Async.Do((Dlg)MyVoidMethod);</param> /// <param name="state">A user object that can be tracked through the returned result</param> /// <param name="tryThreadPool">True to use the TP, otherwise just go to a ful lthread - good for long running tasks.</param> /// <param name="rMode">If true, will make sure no other instances are running your method.</param> /// <returns>AsyncRes with all kind o' goodies for waiting, result values, etc.</returns> public static AsyncRes Do(Dlg d, object state, bool tryThreadPool, ReenteranceMode rMode) { return Do(null, d, false, state, tryThreadPool, rMode, null, true); }
/// <summary> /// Fires off your delegate asyncronously, using the threadpool or a full managed thread if needed. /// </summary> /// <param name="d">A void delegate - can be cast to (Action) from an anonymous delgate.</param> /// <param name="dr">A delegate with a return value of some sort - can be cast to (Func<object>) from an anonymous delgate with a return.</param> /// <param name="state">A user object that can be tracked through the returned result</param> /// <param name="getRetVal">If true, and the method/delgete returns something, it is included in the AsyncRes returned (after the method completes)</param> /// <param name="tryThreadPool">True to use the TP, otherwise just go to a ful lthread - good for long running tasks.</param> /// <param name="rMode">If true, will make sure no other instances are running your method.</param> /// <returns>AsyncRes with all kind of goodies for waiting, result values, etc.</returns> private static AsyncRes Do(Func<object> dr, Action d, bool getRetVal, object state, bool tryThreadPool, ReenteranceMode rMode, bool isAsync, Dispatcher dispatcher) { //get a generic MethodInfo for checks.. MethodInfo mi = ((dr != null) ? dr.Method : d.Method); //make a unique key for output usage string key = string.Format("{0}{1}{2}{3}", ((getRetVal) ? "<-" : ""), mi.DeclaringType, ((mi.IsStatic) ? ":" : "."), mi.Name); //our custom return value, holds our delegate, state, key, etc. AsyncRes res = new AsyncRes(state, ((dr != null) ? (Delegate)dr : (Delegate)d), key, rMode); //Create a delegate wrapper for what we will actually invoke.. Action Action = (Action)delegate { if (!BeforeInvoke(res)) return; //checks for reentrance issues and sets us up try { if (res.IsCompleted) return; if (dr != null) { res.retVal = dr();//use this one if theres a return } else { d();//otherwise the simpler Action } } catch (Exception ex) { //we never want a rogue exception on a random thread, it can't bubble up anywhere System.Diagnostics.Debug.WriteLine("Async Exception:" + ex); } finally { FinishInvoke(res);//this will fire our callback if they used it, and clean up } }; if (dispatcher != null) { res.control = dispatcher; res.result = AsyncAction.ControlInvoked; if (!isAsync) { if (dispatcher.CheckAccess()) { res.completedSynchronously = true; Action(); } else { dispatcher.BeginInvoke(Action); } } else { dispatcher.BeginInvoke(Action); } return res; } //don't catch these errors - if this fails, we shouldn't try a real thread or threadpool! if (tryThreadPool) { //we are going to use the .NET threadpool try { //this is what actually fires this task off.. bool result = ThreadPool.QueueUserWorkItem(delegate { Action(); }); if (result) { res.result = AsyncAction.ThreadPool; //this means success in queueing and running the item return res; } else { //according to docs, this "won't ever happen" - exception instead, but just for kicks. System.Diagnostics.Debug.WriteLine("Failed to queue in threadpool. Method: " + key); } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("Failed to queue in threadpool: " + ex.Message, "Method: " + key); } } //if we got this far, then something up there failed, or they wanted a dedicated thread Thread t = new Thread((ThreadStart)delegate { Action(); }) { IsBackground = true, Name = ("Async_" + key) }; res.result = AsyncAction.Thread; t.Start(); return res; }
/// <summary> /// Fires off your delegate asyncronously, using the threadpool or a full managed thread if needed. /// </summary> /// <param name="d">A void delegate - can be cast to (Dlg) from an anonymous delgate.</param> /// <param name="dr">A delegate with a return value of some sort - can be cast to (DlgR) from an anonymous delgate with a return.</param> /// <param name="state">A user object that can be tracked through the returned result</param> /// <param name="getRetVal">If true, and the method/delgete returns something, it is included in the AsyncRes returned (after the method completes)</param> /// <param name="tryThreadPool">True to use the TP, otherwise just go to a ful lthread - good for long running tasks.</param> /// <param name="rMode">If true, will make sure no other instances are running your method.</param> /// <returns>AsyncRes with all kind o' goodies for waiting, result values, etc.</returns> private static AsyncRes Do(DlgR dr, Dlg d, bool getRetVal, object state, bool tryThreadPool, ReenteranceMode rMode, Control control, bool async) { //get a generic MethodInfo for checks.. MethodInfo mi = ((dr != null) ? dr.Method : d.Method); //make a unique key for output usage string key = string.Format("{0}{1}{2}{3}", ((getRetVal) ? "<-" : ""), mi.DeclaringType, ((mi.IsStatic) ? ":" : "."), mi.Name); //our custom return value, holds our delegate, state, key, etc. AsyncRes res = new AsyncRes(state, ((dr != null) ? (Delegate)dr : (Delegate)d), key, rMode); //Create a delegate wrapper for what we will actually invoke.. Dlg dlg = (Dlg)delegate { if (!BeforeInvoke(res)) return; //checks for reentrance issues and sets us up try { if (res.IsCompleted) return; if (dr != null) { res.retVal = dr();//use this one if theres a return } else { d();//otherwise the simpler dlg } } catch (Exception ex) { //we never want a rogue exception on a random thread, it can't bubble up anywhere GSharp.Logging.Log.Exception("Error during async Invoke", ex); } finally { FinishInvoke(res);//this will fire our callback if they used it, and clean up } }; if (control != null) { try { res.control = control; res.result = AsyncAction.ControlInvoked; if (!async) { if (!control.InvokeRequired) { res.completedSynchronously = true; dlg(); } else { control.Invoke(dlg); } } else { control.BeginInvoke(dlg); } } catch (Exception ex) { GSharp.Logging.Log.Exception("Error during async Invoke", ex); } return res; } //don't catch these errors - if this fails, we shouldn't try a real thread or threadpool! if (tryThreadPool) { //we are going to use the .NET threadpool try { //get some stats - much better than trying and silently failing or throwing an expensive exception int minThreads, minIO, threads, ioThreads, totalThreads, totalIO; ThreadPool.GetMinThreads(out minThreads, out minIO); ThreadPool.GetAvailableThreads(out threads, out ioThreads); ThreadPool.GetMaxThreads(out totalThreads, out totalIO); //check for at least our thread plus one more in ThreadPool if (threads > minThreads) { //this is what actually fires this task off.. bool result = ThreadPool.QueueUserWorkItem((WaitCallback)delegate { dlg(); }); if (result) { res.result = AsyncAction.ThreadPool; //this means success in queueing and running the item return res; } else { //according to docs, this "won't ever happen" - exception instead, but just for kicks. GSharp.Logging.Log.Error("Failed to queue in threadpool. Method: " + key); } } else { GSharp.Logging.Log.Error(String.Format("Insufficient idle threadpool threads: {0} of {1} - min {2}, Method: {3}", threads, totalThreads, minThreads, key)); } } catch (Exception ex) { GSharp.Logging.Log.Exception("Failed to queue in threadpool: " + ex.Message + " Method: " + key, ex); } } //if we got this far, then something up there failed, or they wanted a dedicated thread Thread t = new Thread((ThreadStart)delegate { dlg(); }); t.IsBackground = true; //this or threadpriority are candidates for additional settings t.Name = "Async_" + key; res.result = AsyncAction.Thread; t.Start(); return res; }
/// <summary> /// Fires off your delegate asyncronously, using the threadpool or a full managed thread if needed. /// </summary> /// <param name="d">A void delegate - can be cast to (Action) from an anonymous delgate or method: Async.Do((Action)MyVoidMethod);</param> /// <param name="state">A user object that can be tracked through the returned result</param> /// <param name="async">Whether to run async, or try on current thread if invoke is not required.</param> /// <param name="rMode">If true, will make sure no other instances are running your method.</param> /// <param name="dispatcher">A dispatcher to Invoke upon GUI thread of, if needed. Null if unused.</param> /// <returns>AsyncRes with all kind of goodies for waiting, result values, etc.</returns> public static AsyncRes UI(Action d, Dispatcher dispatcher, object state, bool isAsync, ReenteranceMode rMode) { return Do(null, d, false, state, false, rMode, isAsync, dispatcher); }
/// <summary> /// Fires off your delegate asyncronously, using the threadpool or a full managed thread if needed. /// </summary> /// <param name="d">A delegate with a return value of some sort - can be cast to (DlgR) from an anonymous delgate with a return: Async.Do((DlgR)MyMethod);</param> /// <param name="rMode">If true, will make sure no other instances are running your method.</param> /// <param name="getRetVal">If true, and the method/delgete returns something, it is included in the AsyncRes returned (after the method completes)</param> /// <returns>AsyncRes with all kind o' goodies for waiting, resturn and result values, etc.</returns> public static AsyncRes Do(DlgR d, bool getRetVal, ReenteranceMode rMode) { return Do(d, null, getRetVal, null, true, rMode, null, true); }
/// <summary> /// Fires off your delegate asyncronously, using the threadpool or a full managed thread if needed. /// </summary> /// <param name="d">A delegate with a return value of some sort - can be cast to (Func<object>) from an anonymous delgate with a return: Async.Do((Func<object>)MyMethod);</param> /// <param name="state">A user object that can be tracked through the returned result</param> /// <param name="async">Whether to run async, or try on current thread if invoke is not required.</param> /// <param name="getRetVal">If true, and the method/delgete returns something, it is included in the AsyncRes returned (after the method completes)</param> /// <param name="rMode">If true, will make sure no other instances are running your method.</param> /// <param name="dispatcher">A dispatcher to Invoke upon GUI thread of, if needed. Null if unused.</param> /// <returns>AsyncRes with all kind of goodies for waiting, result values, etc.</returns> public static AsyncRes UI(Func<object> d, bool getRetVal, Dispatcher dispatcher, object state, bool isAsync, ReenteranceMode rMode) { return Do(d, null, getRetVal, state, false, rMode, isAsync, dispatcher); }
/// <summary> /// Fires off your delegate asyncronously, using the threadpool or a full managed thread if needed. /// </summary> /// <param name="d">A void delegate - can be cast to (Dlg) from an anonymous delgate or method: Async.Do((Dlg)MyVoidMethod);</param> /// <param name="rMode">If true, will make sure no other instances are running your method.</param> /// <returns>AsyncRes with all kind o' goodies for waiting, result values, etc.</returns> public static AsyncRes Do(Dlg d, ReenteranceMode rMode) { return(Do(null, d, false, null, true, rMode)); }
/// <summary> /// Fires off your delegate asyncronously, using the threadpool or a full managed thread if needed. /// </summary> /// <param name="d">A delegate with a return value of some sort - can be cast to (Func<object>) from an anonymous delgate with a return: Async.Do((Func<object>)MyMethod);</param> /// <param name="rMode">If true, will make sure no other instances are running your method.</param> /// <param name="getRetVal">If true, and the method/delgete returns something, it is included in the AsyncRes returned (after the method completes)</param> /// <returns>AsyncRes with all kind of goodies for waiting, resturn and result values, etc.</returns> public static AsyncRes Do(Func<object> d, bool getRetVal, ReenteranceMode rMode) { return Do(d, null, getRetVal, null, true, rMode, true, null); }
/// <summary> /// Fires off your delegate asyncronously, using the threadpool or a full managed thread if needed. /// </summary> /// <param name="d">A void delegate - can be cast to (Dlg) from an anonymous delgate or method: Async.Do((Dlg)MyVoidMethod);</param> /// <param name="state">A user object that can be tracked through the returned result</param> /// <param name="tryThreadPool">True to use the TP, otherwise just go to a ful lthread - good for long running tasks.</param> /// <param name="rMode">If true, will make sure no other instances are running your method.</param> /// <returns>AsyncRes with all kind o' goodies for waiting, result values, etc.</returns> public static AsyncRes Do(Dlg d, object state, bool tryThreadPool, ReenteranceMode rMode) { return(Do(null, d, false, state, tryThreadPool, rMode)); }
/// <summary> /// Fires off your delegate asyncronously, using the threadpool or a full managed thread if needed. /// </summary> /// <param name="d">A void delegate - can be cast to (Action) from an anonymous delgate.</param> /// <param name="dr">A delegate with a return value of some sort - can be cast to (Func<object>) from an anonymous delgate with a return.</param> /// <param name="state">A user object that can be tracked through the returned result</param> /// <param name="getRetVal">If true, and the method/delgete returns something, it is included in the AsyncRes returned (after the method completes)</param> /// <param name="tryThreadPool">True to use the TP, otherwise just go to a ful lthread - good for long running tasks.</param> /// <param name="rMode">If true, will make sure no other instances are running your method.</param> /// <returns>AsyncRes with all kind of goodies for waiting, result values, etc.</returns> private static AsyncRes Do(Func <object> dr, Action d, bool getRetVal, object state, bool tryThreadPool, ReenteranceMode rMode, bool isAsync, Dispatcher dispatcher) { //get a generic MethodInfo for checks.. MethodInfo mi = ((dr != null) ? dr.Method : d.Method); //make a unique key for output usage string key = string.Format("{0}{1}{2}{3}", ((getRetVal) ? "<-" : ""), mi.DeclaringType, ((mi.IsStatic) ? ":" : "."), mi.Name); //our custom return value, holds our delegate, state, key, etc. AsyncRes res = new AsyncRes(state, ((dr != null) ? (Delegate)dr : (Delegate)d), key, rMode); //Create a delegate wrapper for what we will actually invoke.. Action Action = (Action) delegate { if (!BeforeInvoke(res)) { return; //checks for reentrance issues and sets us up } try { if (res.IsCompleted) { return; } if (dr != null) { res.retVal = dr();//use this one if theres a return } else { d();//otherwise the simpler Action } } catch (Exception ex) { //we never want a rogue exception on a random thread, it can't bubble up anywhere System.Diagnostics.Debug.WriteLine("Async Exception:" + ex); } finally { FinishInvoke(res);//this will fire our callback if they used it, and clean up } }; if (dispatcher != null) { res.control = dispatcher; res.result = AsyncAction.ControlInvoked; if (!isAsync) { if (dispatcher.CheckAccess()) { res.completedSynchronously = true; Action(); } else { dispatcher.BeginInvoke(Action); } } else { dispatcher.BeginInvoke(Action); } return(res); } //don't catch these errors - if this fails, we shouldn't try a real thread or threadpool! if (tryThreadPool) { //we are going to use the .NET threadpool try { //this is what actually fires this task off.. bool result = ThreadPool.QueueUserWorkItem(delegate { Action(); }); if (result) { res.result = AsyncAction.ThreadPool; //this means success in queueing and running the item return(res); } else { //according to docs, this "won't ever happen" - exception instead, but just for kicks. System.Diagnostics.Debug.WriteLine("Failed to queue in threadpool. Method: " + key); } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine("Failed to queue in threadpool: " + ex.Message, "Method: " + key); } } //if we got this far, then something up there failed, or they wanted a dedicated thread Thread t = new Thread((ThreadStart) delegate { Action(); }) { IsBackground = true, Name = ("Async_" + key) }; res.result = AsyncAction.Thread; t.Start(); return(res); }