C# Source Code: Invoking a method with a timeout
[
Home
|
Contents
|
Search
|
Reply
| Previous | Next ]
C# Source Code
Invoking a method with a timeout
By:
Andrew Baker
Email (spam proof):
Email the originator of this post
Date:
Thursday, January 12, 2006
Hits:
4421
Category:
Threading/Asynchronous operations
Article:
If is often useful to be able to invoke a method, but also to specify a timeout (eg when connecting to a database or a service). The code below contains a class called MethodInvokerTimeout. This class allows a user to execute a method (using a delegate) specifying a timeout. The code includes a test class which demonstrates the intended use of the MethodInvokerTimeout class. using System; using System.Diagnostics; using System.Threading; using System.Runtime.Serialization; #region TestClass ///
/// Demonstration class for MethodInvokerTimeout object ///
class TestClass { ///
/// The main entry point for the application. ///
[STAThread] static void Main(string[] args) { Console.WriteLine("TEST 1 ---- WILL TIMEOUT"); bool failed = false; try { // Create a method invoker that will timeout MethodInvokerTimeout testConnect = new MethodInvokerTimeout( new MethodInvokerCallback( Connect ) ); // Will fail testConnect.TryInvoke( 100 ); failed = true; } catch ( Exception ex ) { // Success (should timeout) failed = false; Console.WriteLine( "Success: Timeout Error = " + ex.Message); } // Check results if ( failed ) { Debug.Fail("MethodInvoker should have timed out"); } else { Console.WriteLine( "MethodInvoker correctly timed out"); } Console.WriteLine("TEST 2 ---- WILL NOT TIMEOUT"); failed = false; try { // Create a method invoker that will timeout MethodInvokerTimeout testConnect = new MethodInvokerTimeout( new MethodInvokerCallback( Connect ) ); // Will succeed testConnect.TryInvoke( 300000 ); failed = false; } catch { // Failed (should NOT timeout) failed = true; } // Check results if ( failed ) { Debug.Fail("MethodInvoker should NOT have timed out"); } else { Console.WriteLine( "MethodInvoker did not timeout"); } Console.ReadLine(); } public static void Connect() { Console.WriteLine("Connecting to database (Sleeping for 2 secs)"); Thread.Sleep(2000); } } #endregion TestClass #region Delegates ///
/// Delegate for invoking the method. ///
public delegate void MethodInvokerCallback(); ///
/// Delegate for invoking the method using parameters. ///
public delegate void MethodInvokerParamCallback(object state); #endregion Delegates #region MethodInvokerTimeout Class ///
/// Class used for invoking methods with a specified timeout. ///
public class MethodInvokerTimeout { #region Member Variables private Delegate _callbackDelegate = null; private object[] _args = null; #endregion Member Variables #region Constructors ///
/// Constructor which takes the delegate containing the method to invoke (with parameters). ///
///
The delegate containing the method to invoke. ///
The parameters to invoke the delegate with. public MethodInvokerTimeout( Delegate callbackDelegate, params object[] args ) : this( callbackDelegate ) { _args = args; } ///
/// Constructor which takes the delegate containing the method to invoke. ///
///
The delegate containing the method to invoke. public MethodInvokerTimeout( Delegate callbackDelegate ) { if ( callbackDelegate == null ) { throw new ArgumentNullException("callbackDelegate", "The callback delegate cannot be null"); } _callbackDelegate = callbackDelegate; } #endregion Constructors #region Public Methods ///
/// Attempts to invoke the method within the given timeout period (in ms). ///
///
The timeout (in ms). ///
Thrown when the timeout expires.
///
Thrown if the timeout is less than 0.
///
Thrown if the MethodInvokerCallback is null.
public void TryInvoke( int timeout ) { // Check parameters if ( timeout < 1 ) { throw new ArgumentOutOfRangeException("timeout", timeout, "The timeout must be greater than zero."); } WaitCallback invoker = new WaitCallback( _PerformInvoke ); IAsyncResult result = invoker.BeginInvoke( null , null, null ); bool completed = result.AsyncWaitHandle.WaitOne( timeout, true ); // Check if we completed. if ( !completed ) { if ( _callbackDelegate != null ) { throw new TimeoutException("Failed to complete method '" + _callbackDelegate.Method.Name + "' within " + FormatLib.Display( timeout ) + " milliseconds."); } else { throw new TimeoutException("Failed to complete method '" + invoker.Method.Name + "' within " + FormatLib.Display( timeout ) + " milliseconds."); } } else { // Call EndInvoke (prevents memory leaks) if ( _callbackDelegate != null ) { invoker.EndInvoke( result ); } else { invoker.EndInvoke( result ); } } } #endregion Public Methods #region Private Methods ///
/// Invokes the delegates. ///
///
Required for method signature but not invoked. private void _PerformInvoke( object notused ) { _callbackDelegate.DynamicInvoke( _args ); } #endregion } #endregion MethodInvokerTimeout Class
Terms and Conditions
Support this site
Download a trial version of the best FTP application on the internet