WhenProgramAfter an asynchronous call is started, the caller thread must have a method to know the invocation status of the call and retrieve the execution result after the call is executed.
You can use either of the following methods:
I. Use round robin
Now let's transform the sample program in the previous section. We can let the computer output a small point to the console at intervals during the asynchronous call process of the program, telling the user that the search is in progress,
This greatly improves the user friendliness of the program.
Example program:
Namespace Asynccalculatefoldersize2
{
Class Program
{
// Calculates the total capacity of a specified folder.
Private Static Long Calculatefoldersize ( String Foldername)
{
If (Directory. exists (Foldername) = False )
{
Throw New Directorynotfoundexception ( " Folder does not exist " );
}
Directoryinfo rootdir = New Directoryinfo (Foldername );
// Get all subfolders
Directoryinfo [] childdirs = rootdir. getdirectories ();
// Get all files in the current folder
Fileinfo [] files = rootdir. getfiles ();
Long Totalsize = 0 ;
// Accumulate the size of each file
Foreach (Fileinfo File In Files)
{
Totalsize + = file. length;
}
// Execute the same calculation process for each folder: Accumulate the size of each file
// This is implemented through recursive calls.
Foreach (Directoryinfo dir In Childdirs)
{
Totalsize + = calculatefoldersize (dir. fullname );
}
// Total size of returned folders
Return Totalsize;
}
// Define a delegate
Public Delegate Long Calculatefoldersizedelegate ( String Foldername );
Static Void Main (String [] ARGs)
{
// Define a delegate variable reference static method calculatefoldersize
Calculatefoldersizedelegate d = calculatefoldersize;
Console. writeline ( " Enter the folder name (for example, c: \ Windows ): " );
String Foldername = console. Readline ();
// Call the static method calculatefoldersize asynchronously through delegation
Iasyncresult ret = D. begininvoke (Foldername, Null , Null );
Console. Write ( " Computing... please wait. " );
While (Ret. iscompleted = False )
{
Console. Write ( " . " );
// Check every 2 seconds
System. Threading. thread. Sleep ( 2000 );
}
// Blocking. Wait until the call is complete and retrieve the result.
Long Size = D. endinvoke (RET );
Console. writeline ( " \ N computing is complete. The size of the folder {0} is {1} bytes \ n " , Foldername, size );
Console. readkey ();
}
}
}
In the above program, after the asynchronous call is started, the status of the asynchronous call is regularly queried. If the status is not completed yet, a small point is output.
The iasyncresult interface has an iscompleted field that can be used to check whether the asynchronous call is complete.
Ii. Use the waiting handle
The aboveCodeRound-Robin iasyncresult. iscompleted attribute values are used to continuously query whether the asynchronous call is complete. You can also use asyncwaithandle, another attribute provided by iasyncresult.
For the same purpose. Asyncwaithanle is a waiting handle object, which defines a series of overloaded waitone methods. We will use the following:
Public Virtual bool waitone (INT millisecondstimeout );
When the preceding waitone method is called, the caller thread changes the status of the "Waiting handle" object to signaled within the period specified by the method parameter millisecondstimeout.
The waitone method returns true. If it times out, false is returned.
The sample code is as follows:
Namespace Asynccalculatefoldersize3
{
Class Program
{
// Calculates the total capacity of a specified folder.
Private Static Long Calculatefoldersize ( String Foldername)
{
If (Directory. exists (Foldername) = False )
{
Throw New Directorynotfoundexception ( " Folder does not exist " );
}
Directoryinfo rootdir = New Directoryinfo (Foldername );
// Get all subfolders
Directoryinfo [] childdirs = rootdir. getdirectories ();
// Get all files in the current folder
Fileinfo [] files = rootdir. getfiles ();
Long Totalsize = 0 ;
// Accumulate the size of each file
Foreach (Fileinfo File In Files)
{
Totalsize + = file. length;
}
// Execute the same calculation process for each folder: Accumulate the size of each file
// This is implemented through recursive calls.
Foreach (Directoryinfo dir In Childdirs)
{
Totalsize + = calculatefoldersize (dir. fullname );
}
// Total size of returned folders
Return Totalsize;
}
// Define a delegate
Public Delegate Long Calculatefoldersizedelegate ( String Foldername );
Static Void Main ( String [] ARGs)
{
// Define a delegate variable reference static method calculatefoldersize
Calculatefoldersizedelegate d = calculatefoldersize;
Console. writeline ( " Enter the folder name (for example, c: \ Windows ): " );
String Foldername = console. Readline ();
// Call the static method calculatefoldersize asynchronously through delegation
Iasyncresult ret = D. begininvoke (Foldername, Null , Null );
Console. Write ( " Computing... please wait. " );
While (! Ret. asyncwaithandle. waitone ( 2000 ))
{
// Wait 2 seconds and output a "."
Console. Write ( " . " );
}
// Blocking. Wait until the call is complete and retrieve the result.
Long Size = D. endinvoke (RET );
Console. writeline ( " \ N computing is complete. The size of the folder {0} is {1} bytes \ n " , Foldername, size );
Console. readkey ();
}
}
}
Iii. asynchronous callback
In the previous two examples, the round robin method is used to continuously check whether the asynchronous call is complete, which will undoubtedly waste a lot of CPU time. Whether the asynchronous call method can automatically call a method at the end, and
Is the processing result displayed in this method?
Asynchronous callback can meet this requirement.
The last two parameters in the begininvoke method definition are "asynccallback callback" and "Object asyncstate", which are used for asynchronous calls.
The following is the sample code:
Namespace Asynccalculatefoldersize4
{
Class Program
{
// Calculates the total capacity of a specified folder.
Private Static Long Calculatefoldersize (String Foldername)
{
If (Directory. exists (Foldername) = False )
{
Throw New Directorynotfoundexception ( " Folder does not exist " );
}
Directoryinfo rootdir = New Directoryinfo (Foldername );
// Get all subfolders
Directoryinfo [] childdirs = rootdir. getdirectories ();
// Get all files in the current folder
Fileinfo [] files = rootdir. getfiles ();
Long Totalsize = 0 ;
// Accumulate the size of each file
Foreach (Fileinfo FileIn Files)
{
Totalsize + = file. length;
}
// Execute the same calculation process for each folder: Accumulate the size of each file
// This is implemented through recursive calls.
Foreach (Directoryinfo dir In Childdirs)
{
Totalsize + = calculatefoldersize (dir. fullname );
}
// Total size of returned folders
Return Totalsize;
}
Public Delegate Long Calculatefoldersizedelegate ( String Foldername );
Private Static Calculatefoldersizedelegate d = calculatefoldersize;
// Function used for callback
Public Static Void Showfoldersize (iasyncresult result)
{
Long Size = D. endinvoke (result );
Console. writeline ( " \ N folder {0} capacity: {1} bytes \ n " , (String) result. asyncstate, size );
}
Static Void Main ( String [] ARGs)
{
String Foldername;
While ( True )
{
Console. writeline ( " Enter the folder name (for example, c: \ Windows) and the quit end program " );
Foldername = console. Readline ();
If (Foldername = " Quit " )
Break ;
D. begininvoke (Foldername, showfoldersize, Foldername );
}
}
}
}
Note:
1. The code that calls the begininvoke method. The 2nd parameters of the begininvoke method specify that the showfoldersize method is called back when the asynchronous call ends. The 3rd parameters asyncstate are filled in the folder to be calculated.
Name. This value is encapsulated by the begininvoke method into an automatically created iasyncresult type object, it is automatically transmitted to the callback method as a method real parameter (that is, the result parameter of the callback method showfoldersize in this example ),
The callback method obtains the value through the asyncstate field of this real parameter.
2. the return value type of the callback method is void. Only one iasyncresult type parameter result is allowed, and the endinvoke method must be called in the method body to retrieve the execution result of the method. In addition, asyncstate of result Parameter
The property contains the parameter information (in this example, the folder name) passed in from the outside world ).
This program can now Input Multiple folder names consecutively. The computer calculates the names separately in the background and then outputs the results in the console window.
Note: The first Input Folder (the first task to be executed) is not necessarily completed first, but the subsequent task may be executed first due to a small workload.
Here we can draw a conclusion: If you need to transmit some additional information to the callback method, put it into the 3rd parameter asyncsate of the begininvoke method. Notes
This parameter is of the object type, so any type of data can be placed. (This parameter will be mentioned later. In fact, most asynchronous methods in the class library have this parameter )!