According to the resource types required for the operation, we can divide the operation into cpu-bound operations and I/O-bound operations, the former is mainly to use cpu for intensive operations, the latter spends most of its processing time on I/O processing (such as file systems and network resources ). For I/O Binding operations, we can make full use of the multi-threaded mechanism, so that multiple operations can be executed in parallel on their respective threads.
Service calling is a typical I/O binding operation. Therefore, multithreading is widely used in service calling. Based on the location where asynchronous operations occur, asynchronous operations of wcf applications can be divided into three types:
1. asynchronous channel call: the client sends messages to the server through the channel bound to the creation, thus calling the service. The client can call the asynchronous service through the asynchronous call Channel of the proxy object.
2. One-way message exchange: the client channel sends messages to the server in one-way message exchange mode. Once a message arrives at the transport layer, it is returned immediately to achieve asynchronous service calling.
3. asynchronous service implementation: the server uses the asynchronous call method when implementing service operations.
1. Call of asynchronous services
Create an asynchronous Service Proxy
Generally, service proxies inherit from ClientBase <TChannel>. By default, operations that do not have asynchronous service calls are performed. However, we can create an asynchronous Service proxy by adding a reference and call the Service asynchronously.
When adding a service reference, click "advanced" in the displayed service reference dialog box. The service reference Settings dialog box is displayed, and select "generate asynchronous operation ".
There will be several more methods in the generated Service proxy class (the calculation service is used as an example below). The following methods will be introduced in the following sections.
[Csharp]
Public partial class CalculatorClient: ClientBase <ICalculator>, ICalculator
{
Public event System. EventHandler <AddCompleteArgs> AddComplete;
Public IAsyncResult BeginAdd (double x, double y, AsyncCallback callback, object asuncState );
Public double EndAdd (System. IAsyncReuslt result );
Public AddAsync (double x, double y );
Public AddAsync (double x, double y, object userState );
}
Here, Add is used for Synchronous service calls, while BeginAdd/EndAdd is used for asynchronous calls. Note that the AsyncPattern attribute of the OperationContractAttributes attribute applied to the BeginAdd method is set to True.
1. asynchronous service calling through BeginXxx/EndXxx
Call the BeginXxx method to execute corresponding operations in another thread. The method immediately returns an IAsyncResult object. At this time, we can execute additional operations in the current thread. The result of Asynchronous Operation execution is obtained by calling the EndXxx method, and the parameter of this method is the IAsyncResult object obtained by calling the BeginXxx method. The following example shows how to add a computing service reference to generate a proxy type CalculatorClient.
[Csharp]
CalculatorClient proxy = new CalculatorClient ();
IAsyncResult asyncResult = proxy. BeginAdd (1, 2, null, null );
// Other operations
// The Endxx method can be called Based on the possible execution time of asynchronous operations. Once the Endxxx method is called, the current thread is blocked until the asynchronous operation ends.
Double result = proxy. EndAdd (asyncResult );
Proxy. Close ();
Console. WriteLine ("x + y = {2} when x = {0} and y = {1}", 1, 2, result );
Note: An extreme example is that the EndXxx method is called directly after the BeginXxx method is called. Although it is in different threads, it basically does not play an asynchronous role, the callback method can be used to solve this problem.
2. asynchronous service calling through callback
Let's take a look at the BeginAdd methods in the above several methods in the Service proxy class.
Public IAsyncResult BeginAdd (double x, double y, AsyncCallback callback, object asyncState );
① The parameter type is AsyncCallback's callback, and AsyncCallback is a delegate whose parameter type is IAsyncResult and has no return value,
② The asyncState parameter can be used to pass some additional parameters to the callback operation. The asyncState specified in the BeginAdd method can be obtained through the AsyncState attribute of IAsyncResult;
[Csharp]
Public delegate void AsyncCallback (IAsyncResult ar );
Public interface IAsyncResult
{
Object AsyncState {get ;}
WaitHandle AsyncWaitHandle {get ;}
Bool CompletedSynchronously {get ;}
Bool IsCompleted {get ;}
}
The following uses an anonymous method to define a callback operation. because the number of involved operations is required to output the operation result in the callback operation, we use the asyncState parameter of the BeginAdd method to transmit data to the callback operation.
In the callback operation, the operations are obtained through the AsyncState of the IAsyncResult object.
[Csharp]
CalculatorClient proxy = new CalculatorClient ();
Proxy. BeginAdd (1, 2,
Delegate (IAsyncResult asyncResult)
{
Double [] operNums = asyncResult. AsyncState as double [];
Double result = proxy. EndAdd (asyncResult );
Proxy. Close ();
Console. WriteLine ("x + y = {2} when x = {0} and y = {1}", operNums [0], operNums [2], result );
}, New double [] {1, 2 });
3. asynchronous service calling through event registration
There are two AddAsync method reloads and an AddComplete event asynchronously executed in the asynchronous Service proxy class.
Public AddAsync (double x, double y );
Public AddAsync (double x, double y, object userState );
The userState parameter has the same effect as the asyncState parameter of the BeginAdd method.
[Csharp]
Public event System. EventHandler <AddCompleteEventArgs> AddComplete;
Public class AddCompleteEventArgs: EventArgs
{
Public bool Cancelled {get ;}
Public Exception Error {get ;}
Public object UserState {get ;}
}
The event parameter AddCompleteEventArgs defines three read-only attributes. Cancelled indicates whether the asynchronous operation is canceled. If an Asynchronous Operation throws an exception, you can use the attribute Error. UserState returns the userState parameter in Addsync.
Because the AddAsync method is executed asynchronously, it will be returned immediately after the call. If we have registered the AddComplete event of CalculatorClient, it will be triggered after the asynchronous service call ends, so we can call the Addsync method of the Service proxy as follows:
[Csharp]
CalculatorClient proxy = new CalculatorClient ();
Proxy. AddComplete + = delegate (object sender, AddCompleteEventArgs args)
{
Double [] operNums = args. UserState as double [];
Double result = args. Result;
Proxy. Close ();
Console. WriteLine ("x + y = {2} when x = {0} and y = {1}", operNums [0], operNums [2], result );
};
Proxy. AddAsync (1, 2, new double [] {1, 2 });
II. Implementation of asynchronous services
The above describes how to call asynchronous services, but how to implement service operations in asynchronous mode?
Asynchronous Operation Mode
As mentioned above, the AsyncPattern attribute of OperationContractAttributes is applied to an operation method. If it is set to True, the corresponding operation needs to be implemented in asynchronous mode, in fact, the contract interface of the asynchronous Service proxy class generated by the client also contains such asynchronous operations.
Asynchronous service operations are implemented by pairing BeginXxx/EndXxx. You only need to set the attribute AsyncPattern to True based on the BeginXx method feature.
III. The example demonstrates how to define a file reading service in asynchronous mode.
Client read:
,
Author: lordbaby