ASYNCRONOUS METHOD'S DEFINTION AND DELEGATES AS CALLBACK METHOD
An asynchronous method call is a method used in .NET programming that returns to the caller immediately before the completion of its processing and without blocking the calling thread.
When an application calls an asynchronous method, it can simultaneously execute along with the execution of the asynchronous method that performs its task. An asynchronous method runs in a thread separate from the main application thread. The processing results are fetched through another call on another thread.
Asynchronous methods help optimize the execution of resources resulting in scalable application. These are used to execute time-consuming tasks such as opening large files, connecting to remote computers, querying a database, calling Web services and ASP.NETWeb forms.
Asynchronous method call may also be referred to as asynchronous method invocation (AMI).
NET framework provides two design patterns to implement the asynchronous method, which are those using asynchronous delegates (IASyncResult objects) and events. Asynchronous delegates' pattern is more complex and provides flexibility, which makes it well-suited to various complex programming models. The event-based model is simple and should be used in most cases.
In the asynchronous delegates pattern, a delegate object uses two methods: BeginInvoke and EndInvoke. BeginInvoke has a list of parameters, which are similar to its wrapped function, along with two additional optional parameters; it returns the IAsyncResult object. EndInvoke returns two parameters (out and ref type) along with the IAsyncResult object. BeginInvoke is used for initiating the asynchronous call, whereas EndInvoke is used to retrieve the results of the asynchronous call.
Events-based asynchronous patterns use a class that has one or more methods, named MethodNameAsync, which have corresponding synchronous versions that execute on the current thread. Events-based patterns may also have a MethodNameCompleted event and MethodNameAsyncCancel method. This pattern enables the class to communicate with pending asynchronous operations using the delegate event model.
Using Delegates as Callback Methods
Used extensively in programming for Microsoft Windows, callback methods are used when you need to pass a function pointer to another function that will then call you back (via the passed pointer). An example would be the Win32 API EnumWindows function. This function enumerates all the top-level windows on the screen, calling the supplied function for each window. Callbacks serve many purposes, but the following are the most common: -
- Asynchronous processing Callback methods are used in asynchronous processing when the code being called will take a good deal of time to process the request. Typically, the scenario works like this: Client code makes a call to a method, passing to it the callback method. The method being called starts a thread and returns immediately. The thread then does the majority of the work, calling the callback function as needed. This has the obvious benefit of allowing the client to continue processing without being blocked on a potentially lengthy synchronous call.
- Injecting custom code into a class's code path Another common use of callback methods is when a class allows the client to specify a method that will be called to do custom processing. Let's look at an example in Windows to illustrate this. Using the Listbox class in Windows, you can specify that the items be sorted in ascending or descending order. Besides some other basic sort options, the Listbox class can't really give you any latitude and remain a generic class. Therefore, the Listbox class also enables you to specify a callback function for sorting. That way, when Listbox sorts the items, it calls the callback function and your code can then do the custom sorting you need.
Now let's look at an example of defining and using a delegate.In this example, we have a database manager class that keeps track of all active connections to the database and provides a method for enumerating those connections. Assuming that the database manager is on a remote server, it might be a good design decision to make the method asynchronous and allow the client to provide a callback method. Note that for a real-world application you'd typically create this as a multithreaded application to make it truly asynchronous. However, to keep the example simple-and because we haven't covered multithreading yet-let's leave multithreading out.
First, let's define two main classes: DBManager and DBConnection.
class DBConnection { } class DBManager { static DBConnection[] activeConnections; public delegate void EnumConnectionsCallback(DBConnection connection); public static void EnumConnections(EnumConnectionsCallback callback) { foreach (DBConnection connection in activeConnections) { callback(connection); } } }
The EnumConnectionsCallback method is the delegate and is defined by placing the keyword delegate in front of the method signature. You can see that this delegate is defined as returning void and taking a single argument: a DBConnection object. The EnumConnectionsmethod is then defined as taking an EnumConnectionsCallback method as its only argument. To call the DBManager. EnumConnections method, we need only pass to it an instantiated DBManager. EnumConnectionCallback delegate.
To do that, you new the delegate, passing to it the name of method that has the same signature as the delegate. Here's an example of that: -
DBManager.EnumConnectionsCallback myCallback = new DBManager.EnumConnectionsCallback(ActiveConnectionsCallback); DBManager.EnumConnections(myCallback);
Also note that you can combine this into a single call like so: -
DBManager.EnumConnections(new DBManager.EnumConnectionsCallback(ActiveConnectionsCallback));
That's all there is to the basic syntax of delegates. Now let's look at the full example application: -
using System; class DBConnection { public DBConnection(string name) { this.name = name; } protected string Name; public string name { get { return this.Name; } set { this.Name = value; } } } class DBManager { static DBConnection[] activeConnections; public void AddConnections() { activeConnections = new DBConnection[5]; for (int i = 0; i < 5; i++) { activeConnections[i] = new DBConnection("DBConnection " + (i + 1)); } } public delegate void EnumConnectionsCallback(DBConnection connection); public static void EnumConnections(EnumConnectionsCallback callback) { foreach (DBConnection connection in activeConnections) { callback(connection); } } } class Delegate1App { public static void ActiveConnectionsCallback(DBConnection connection) { Console.WriteLine("Callback method called for " + connection.name); } public static void Main() { DBManager dbMgr = new DBManager(); dbMgr.AddConnections(); DBManager.EnumConnectionsCallback myCallback = new DBManager.EnumConnectionsCallback(ActiveConnectionsCallback); DBManager.EnumConnections(myCallback); } }
Compiling and executing this application results in the following output: -
Callback method called for DBConnection 1 Callback method called for DBConnection 2 Callback method called for DBConnection 3 Callback method called for DBConnection 4 Callback method called for DBConnection 5
No comments:
Post a Comment