illustrate:
Asynchronous delegate calls are not supported in the .NET Compact Framework, that is, the BeginInvoke and EndInvoke methods.
The BeginInvoke method initiates an asynchronous call. This method has the same parameters as the one you need to execute asynchronously, and there are two other optional parameters. The first parameter is an AsyncCallback delegate that references the method to be called when the asynchronous call is completed. The second parameter is a user-defined object that passes information into the callback method. BeginInvoke will return immediately without waiting for the asynchronous call to complete. BeginInvoke returns an IAsyncResult that can be used to monitor the progress of asynchronous calls.
The EndInvoke method retrieves the results of an asynchronous call. The method can be called at any time after calling BeginInvoke. If the asynchronous call has not been completed, EndInvoke keeps blocking the calling thread until the asynchronous call completes. The parameters of EndInvoke include the out and ref parameters of the method you need to execute asynchronously (<Out> ByRef and ByRef in Visual Basic) and the IAsyncResult returned by BeginInvoke.
illustrate:
The IntelliSense feature in Visual Studio 2005 displays the parameters of BeginInvoke and EndInvoke. If you are not using Visual Studio or similar tools, or you are using C# with Visual Studio 2005, see Asynchronous Programming Overview for instructions on the parameters defined for these methods.
The code examples in this topic demonstrate four common methods for asynchronous calls using BeginInvoke and EndInvoke. After calling BeginInvoke, you can do the following:
Do some operations and then call EndInvoke until the call is completed.
Use the property to get the WaitHandle, use its WaitOne method to block execution until the WaitHandle signal is emitted, and then call EndInvoke.
Poll the IAsyncResult returned by BeginInvoke to determine when the asynchronous call completes, and then call EndInvoke.
Passes the delegate used for the callback method to BeginInvoke. After the asynchronous call is completed, the method is executed on the ThreadPool thread. The callback method calls EndInvoke.
Important Note:
No matter what method you use, call EndInvoke to complete the asynchronous call.
Define test methods and asynchronous delegates
The following code example demonstrates various ways to call the same long-running method TestMethod asynchronously. The TestMethod method displays a console message that the method has started processing, hibernated for a few seconds, and then ends. TestMethod has an out parameter that demonstrates how this parameter is added to the signatures of BeginInvoke and EndInvoke. You can handle the ref parameter in the same way.
The following code example demonstrates the definition of TestMethod and the delegate called AsyncMethodCaller that can be used to asynchronously call TestMethod. To compile a code example, you must include the definition of TestMethod and the AsyncMethodCaller delegation.
C#
using System;
using ;
namespace AsyncTest
{
public class AsyncDemo
{
//Method 1
public string TestMethod(int callDuration, out int threadId)
{
("Test method begins.");
(callDuration);
threadId = ;
return ("My call time was {0}.", ());
}
//Method 2
public float Addxy(float x, float y)
{
return x * y;
}
}
//Define two delegates corresponding to methods, the parameters are the same as the method, and the declaration of the delegate is written in the calling class, without limitation
public delegate string AsyncMethodCaller(int callDuration, out int threadId);
public delegate float AsyncMethodCaller2(float x, float y);
}
Use EndInvoke to wait for an asynchronous call
The easiest way to execute a method asynchronously is to start executing the method by calling the delegated BeginInvoke method, perform some operations on the main thread, and then call the delegated EndInvoke method. EndInvoke may block the calling thread because the method does not return until the asynchronous call is completed. This method is very suitable for executing files or network operations.
Important Note:
Because EndInvoke may block, the method should not be called from a thread serving the user interface.
C#
using System;
using ;
namespace AsyncTest
{
public class AsyncMain
{
public static void Main()
{
// The asynchronous method puts the thread id here.
int threadId;
//Instantiation.
AsyncDemo ad = new AsyncDemo();
// Define the delegation
AsyncMethodCaller caller = new AsyncMethodCaller();
//The callback function is null by delegating the callback function
IAsyncResult result = (3000,
out threadId, null, null);
(0);
("Main thread {0} does some work.",
);
// Call EndInvoke to wait for the asynchronous call to complete, will block
// and to retrieve the results.
string returnValue = (out threadId, result);
("The call executed on thread {0}, with return value \"{1}\".",
threadId, returnValue);
}
}
}
WaitHandle to wait for an asynchronous call
You can get the WaitHandle using the AsyncWaitHandle property of the IAsyncResult returned by BeginInvoke. The WaitHandle signal is emitted when the asynchronous call completes, and you can wait for it by calling the WaitOne method.
If you use WaitHandle, you can perform additional processing before or after the asynchronous call is completed, but before the result is retrieved by calling EndInvoke.
illustrate:
The waiting handle is not automatically closed when calling EndInvoke. If all references to the waiting handle are released, system resources will be released when the garbage collection function recycles the waiting handle. To release system resources immediately after the waiting handle is used, call the method to release the waiting handle. When releasing freeable objects explicitly, garbage collection will work more efficiently.
C#
using System;
using ;
namespace AsyncTest
{
public class AsyncMain
{
static void Main()
{
// The asynchronous method puts the thread id here.
int threadId;
//Instantiation
AsyncDemo ad = new AsyncDemo();
//Define delegation.
AsyncMethodCaller caller = new AsyncMethodCaller();
//Call
IAsyncResult result = (3000,
out threadId, null, null);
(0);
("Main thread {0} does some work.",
);
// Wait for the WaitHandle to become signaled.
();
// Perform additional processing here.
// Call EndInvoke to retrieve the results.
string returnValue = (out threadId, result);
// Close the wait handle.
();
("The call executed on thread {0}, with return value \"{1}\".",
threadId, returnValue);
}
}
}
/*The output is as follows:
Main thread 1 does some work.
Test method begins.
The call executed on thread 3, with return value "My call time was 3000.".
*/
Polling asynchronous call completes
You can use the IsCompleted property of the IAsyncResult returned by BeginInvoke to discover when an asynchronous call completes. This can be done when making asynchronous calls from a service thread in the user interface. Polling completion allows the calling thread to continue execution when an asynchronous call is executed on a ThreadPool thread.
C#C++VB
using System;
using ;
namespace AsyncTest
{
public class AsyncMain
{
static void Main() {
// The asynchronous method puts the thread id here.
int threadId;
//Instantiation.
AsyncDemo ad = new AsyncDemo();
//Declare the delegation
AsyncMethodCaller caller = new AsyncMethodCaller();
//Call.
IAsyncResult result = (3000,
out threadId, null, null);
//Polling.
while( == false) {
(250);
(".");
}
//Get the result.
string returnValue = (out threadId, result);
("\nThe call executed on thread {0}, with return value \"{1}\".",
threadId, returnValue);
}
}
}
/* Output:
Test method begins.
.............
The call executed on thread 3, with return value "My call time was 3000.".
*/
Execute callback method when asynchronous call is completed
If the thread that initiates the asynchronous call does not need to be the thread that processes the result, the callback method can be executed when the call is completed. The callback method is executed on the ThreadPool thread.
To use a callback method, the AsyncCallback delegate representing the callback method must be passed to BeginInvoke. You can also pass an object that contains the information to be used by the callback method. In a callback method, IAsyncResult (the only parameter of the callback method) can be cast to an AsyncResult object. You can then use the property to get the delegate that has been used to initiate the call so that EndInvoke can be called.
Description of the examples:
The threadId parameter of TestMethod is the out parameter (<Out> ByRef in Visual Basic), so TestMethod never uses the input value of the parameter. A dummy variable is passed to the BeginInvoke call. If the threadId parameter is the ref parameter (ByRef in Visual Basic), the variable must be a class-level field so that it can be passed to both BeginInvoke and EndInvoke.
The status information passed to BeginInvoke is a format string that the callback method uses to format the output message. Because it is passed as a type Object, the status information must be cast to the correct type before it can be used.
The callback is performed on the ThreadPool thread. ThreadPool threads are background threads that do not keep the application running after the main thread ends, so the main thread of the example must sleep long enough for the callback to complete.
C#
using System;
using ;
using ;
namespace AsyncTest
{
public class AsyncMain
{
static void Main()
{
//Instantiate the class.
AsyncDemo ad = new AsyncDemo();
//The examples have two different delegations, which correspond to different methods.
AsyncMethodCaller caller = new AsyncMethodCaller();
AsyncMethodCaller2 caller2 = new AsyncMethodCaller2();
// The threadId parameter of TestMethod is an out parameter, so
// its input value is never used by TestMethod. Therefore, a dummy
// variable can be passed to the BeginInvoke call. If the threadId
// parameter were a ref parameter, it would have to be a class-
// level field so that it could be passed to both BeginInvoke and
// EndInvoke.
int dummy = 0;
// Specify the callback method when calling, and the method will be automatically called after asynchronous execution to obtain the execution result
IAsyncResult result = (3000,
out dummy,
new AsyncCallback(CallbackMethod),
"The call executed on thread {0}, with return value \"{1}\".");
(2, 3, CallbackMethod2, "this is add");
("The main thread {0} continues to execute...",
);
(4000);
("The main thread ends.");
}
// The callback method must have the same signature as the
// AsyncCallback delegate.
private void CallbackMethod(IAsyncResult ar)
{
// Retrieve the delegate.
AsyncResult result = (AsyncResult) ar;
//Captive conversion to the corresponding delegate object
AsyncMethodCaller caller = (AsyncMethodCaller) ;
// Retrieve the format string that was passed as state
// information.
string formatString = (string) ;
// Define a variable to receive the value of the out parameter.
// If the parameter were ref rather than out then it would have to
// be a class-level field so it could also be passed to BeginInvoke.
int threadId = 0;
// Call EndInvoke to retrieve the results.
string returnValue = (out threadId, ar);
// Use the format string to format the output message.
(formatString, threadId, returnValue);
}
private void CallbackMethod2(IAsyncResult ar)
{
// Retrieve the delegate.
AsyncResult result = (AsyncResult)ar;
//Captively convert to the corresponding delegate object
AsyncMethodCaller2 caller = (AsyncMethodCaller2);
// Get status
string formatString = (string);
//Calling the asynchronous completed method to obtain the execution result
string returnValue = (ar).ToString();
//This method is used when the Windows application assigns values to the control, because the control cannot be operated without the creation thread
(new Action<string>((u) => tb_datainfo.Text += u), returnValue);
//tb_datainfo.Text = (out threadId, ar);
// Use the format string to format the output message.
//(formatString, threadId, returnValue);
}
}
}
}