The benefits of async before learning async, for example, for input and output operations that do not require CPU parameters, you can divide the actual processing steps into the following three steps:
- Start processing;
- The actual processing, at this time do not need the CPU parameters;
- The processing after the completion of the task;
If you use only one thread for the above steps, the "card" phenomenon occurs when the line is impersonating is handling the UI operation.
If you use asynchronous processing, then this three-step process involves two threads, starting the first step in the main thread, the main thread ends (if it does not end, the thread is left unattended), and the second step does not require CPU involvement; After the second step, start the third step on the second thread ; The second thread ends after completion. No thread in this process needs to be in a waiting state to make the running thread fully utilized.
I. I/O threads for the CLR thread pool
The previous study was a worker thread for the CLR thread pool, this time to learn the I/O thread of the CLR thread pool.
The I/O thread is a thread set up by. NET to access external resources, because access to external resources is often influenced by external factors, and. NET establishes asynchronous methods for multiple I/O operations in order to prevent the main thread from being affected for long-term blocking. For example: FileStream, TCP/IP, WebRequest, WebService, and so on, and each async method is used very similarly,
Start with beginxxx and end with EndXxx (APM). for APM, it must end asynchronously with endxxx, which could cause a resource leak. BeginXxx actually threads the thread into the thread pool.
There is also an event-based asynchronous programming pattern (EPM) that supports the event-based Asynchronous pattern of a class that has one or more methods with the suffix async, and a corresponding event named completed suffix, which is used to initiate asynchronous processing. The completed event will announce the completion of asynchronous processing after the asynchronous processing is complete. Note that the compeleted handler must be called when the EPM mode is used, whether an asynchronous request has been completed, an exception occurred in processing, or a termination of asynchronous processing. Such as:
OpenReadAsync openreadcompleted
Second, asynchronous read-write FileStream
To invoke an I/O thread asynchronously in FileStream, you must establish the FileStream object with the following constructor and set the Useasync to true.
FileStream stream = new FileStream (string Path,filemode mode,fileaccess access,fileshare share,int buffersize,bool UseAsync);
Parameter description:
- Path is the relative or absolute path of the file;
- mode determines how the file is opened or created;
- Access confirms how the file is accessed;
- Share determine how the file process is shared;
- BufferSize is the buffer size, generally the default minimum value is 8, when starting asynchronous read or write, the file size is generally larger than the buffer size;
- Userasync represents whether to start an asynchronous I/O thread.
Note: When using the BeginRead and BeginWrite methods, it is better to perform a lot of reading or writing, but for a small amount of read/write, these methods may be slower than synchronization because it takes a lot of time to switch between threads.
1. Asynchronous write
The FileStream contains BeginWrite, EndWrite methods that can initiate an I/O thread for asynchronous writes.
public override IAsyncResult BeginWrite (byte[] array,int offset,int numbytes,asynccallback,object stateobject) public override void EndWrite (IAsyncResult asyncResult)
The BeginWrite return value is IAsyncResult, and is used in a manner similar to the BeginInvoke method of a delegate, preferably using a callback function to avoid thread blocking.
The last two parameters are the same routine:
- AsyncCallback for binding callback functions;
- object is used to pass external data.
Note that thecallback function that the AsyncCallback binds must be a non-return value method with a single IAsyncResult parameter.
In the example, FileStream is passed to the callback function as an external data, and then the callback function uses IAsyncResult.AsyncState to get the FileStream object, and finally through Filestream.endwrite ( IAsyncResult) End write.
The following is an example of an asynchronous write:
Class Program {static void Main (string[] args) {int A, B; Threadpool.getmaxthreads (out A, out B); Console.WriteLine ("Number of auxiliary threads" + A + "+" number of original I/O threads "+ b); FileName File Creation method file permissions file process share buffer size 1024 whether to start asynchronous I/O thread is true FileStream stream = new FileStream (@ "D:\123.txt", FileMode . OpenOrCreate, FileAccess.ReadWrite, Fileshare.readwrite, 1024x768, true); It is important to note that if you write a small string,. Net writes with a worker thread because it is faster byte[] bytes = Encoding.UTF8.GetBytes ("Are you okay in the other place?" "); The asynchronous write begins, the second-to-last argument specifies the callback function, and the final argument passes itself to the callback function to end the asynchronous thread stream. BeginWrite (bytes, 0, (int) bytes. Length, New AsyncCallback (Callback), stream); Threadpool.getavailablethreads (out A, out B); Console.WriteLine ("Number of existing worker threads" + A + "" + "number of existing I/O threads" + b); Console.WriteLine ("Main thread continues to do other work!"); Console.readkey (); } static void Callback (IAsyncResult result) {//Display thread pool status Thread.Sleep(2000); Through result. AsyncState re-cast to FileStream will be able to get the FileStream object, which ends the asynchronous write FileStream stream = (FileStream) result. asyncstate; Stream. EndWrite (result); Stream. Flush (); Stream. Close (); } }
The output results are as follows:
For a way to end an asynchronous thread, or to play the IAsyncResult, pass the own object to the callback function at the start of the asynchronous write, and get itself in the callback function to end the asynchronous thread.
This is the asynchronous operation in C #, from the number of remaining threads we see that async is actually called the thread pool's threads to implement Async.
2. Asynchronous read
FileStream can be read by invoking the asynchronous I/O thread by using BeginRead and EndRead:
public override IAsyncResult BeginRead (byte[] array,int offset,int numbytes,asynccallback usercallback,object stateobject) public override int EndRead (IAsyncResult asyncResult)
BeginRead and EndRead methods are similar to write, AsyncCallback is used to bind the callback function, and object is used to pass external data. The callback function only needs to use iasyncresult.asyncstate to get the external data. The EndRead method returns the number of bytes read from the stream.
First define the Filedata class, which contains the FileStream object, byte[] array and length. The Filedata object is then passed to the callback function as an external data, and in the callback function, the iasyncresult.asyncstate is cast to Filedata. The read is then finished by Filestream.endread (IAsyncResult).
Finally, the length is compared, and if the length of the read is inconsistent with the input data length, an exception is thrown.
Class Program {static void Main (string[] args) {int A, B; Threadpool.getavailablethreads (out A, out B); Console.WriteLine ("Original worker thread:" + A + "original I/O thread:" + b); byte[] Bytedata = new byte[1024]; FileStream stream = new FileStream (@ "D:\123.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, Fileshare.readwrite, 1024x768, true); Binds data such as FileStream object, byte[] object, length, etc. to the Filedate object and sends it to the callback function Hashtable HT = new Hashtable () in the attached attribute mode; Ht. ADD ("Length", (int) stream. Length); Ht. ADD ("stream", stream); Ht. ADD ("Bytedata", bytedata); Starts an asynchronous read, the second-to-last argument is the specified callback function, and the last argument is the parameter stream passed in the callback function. BeginRead (bytedata, 0, (int) ht["Length"], new AsyncCallback (completed), HT); Threadpool.getavailablethreads (out A, out B); Console.WriteLine ("Existing worker thread:" + A + "existing I/O thread:" + b); Console.readkey (); }//The actual parameter is the callback function static void completed (IasyncResult result) {Thread.Sleep (2000); The parameter result is actually the Hashtable object, with Filestream.endread completing the asynchronous read Hashtable HT = (Hashtable) result. asyncstate; FileStream stream = (FileStream) ht["Stream"]; int length = stream. EndRead (result); Stream. Close (); String str = Encoding.UTF8.GetString (ht["Bytedata"] as byte[]); Console.WriteLine (str); Stream. Close (); } }
The output is as follows:
Note that if the file is too small and less than buffer 1024, the worker thread and not the I/O thread may be invoked. But according to my observations, just reading a file is too small to invoke a worker-thread operation, but not when it is written.
Like above, it is processed directly with the auxiliary thread.
The main function of IAsyncResult is two points:
- The AsyncState property that is used to pass parameters to the callback function;
- The EndXxx method that ends the asynchronous operation method requires this object as a parameter;
Third, asynchronous WebRequest
System.Net.WebRequest is an abstract base class developed by. Net to implement the request/response model for the Internet. It has three main subclasses:
- Ftpwebrequest,filewebrequest uses the URI of the "file://path" to implement the request/response to local resources and internal files;
- Httpwebrequest,ftpwebrequest using FTP File Transfer Protocol to implement file request/response;
- Filewebrequest,httpwebrequest page Request/response for HTTP processing;
When an object is created using WebRequest.Create (string uri), the application can determine the implementation class according to the request protocol FileWebRequest, FtpWebRequest, HttpWebRequest each has its role. As a result of the use of similar methods, the following is the use of common HttpWebRequest as an example of how asynchronous WebRequest used.
HttpWebRequest contains a few common methods for handling requests/responses:
public override Stream Getrequest () public override WebResponse GetResponse () public override IAsyncResult BeginGetRequestStream (AsyncCallback callback,object State) public override Stream EndGetRequestStream ( IAsyncResult asyncResult) Public override IAsyncResult BeginGetResponse (AsyncCallback callback,object State) Public override WebResponse EndGetResponse (IAsyncResult asyncResult)
- BeginGetRequestStream, EndGetRequestStream is used to asynchronously write request information to HttpWebRequest object;
- BeginGetResponse, EndGetResponse is used to asynchronously send a page request and obtain a return letter;
Use an asynchronous operation of the Internet's request/response to prevent the main thread from waiting for a long time while the asynchronous thread is an I/O thread from the CLR thread pool during the operation.
Note: The request and response cannot use synchronous and asynchronous mixed development mode, that is, when the request is written using the GetRequestStream synchronous mode, even if the response uses the BeginGetResponse async method, the operation is also in the same thread as the GetRequestStream method.
Class Program {static void Main (string[] args) {int A, B; Threadpool.getavailablethreads (out A, out B); Console.WriteLine ("Original worker thread:" + A + "original I/O thread:" + b); Use the WebRequest.Create method to establish the HttpWebRequest object HttpWebRequest webRequest = (HttpWebRequest) webrequest.create ("http:/ /www.baidu.com "); Webrequest.method = "POST"; Asynchronously requests the Requeststream object that writes the data IAsyncResult result = Webrequest.begingetresponse (new AsyncCallback (endgetrespons e), webRequest); Thread.Sleep (1000); Threadpool.getavailablethreads (out A, out B); Console.WriteLine ("Existing worker thread:" + A + "existing I/O thread:" + b); Console.WriteLine ("The main thread continues to do other things!"); Console.readkey (); } static void EndGetResponse (IAsyncResult result) {Thread.Sleep (2000); Ends an asynchronous request, obtaining the result HttpWebRequest WebRequest = (HttpWebRequest) result. asyncstate; WebResponse WebResponse = Webrequest.endgetresponse (result); Stream stream = WebResponse.GetResponseStream (); StreamReader sr = new StreamReader (stream); String html = Sr. ReadToEnd (); Console.WriteLine (HTML. Substring (0,50)); } }
The results appear as follows:
Iv. Asynchronous SqlCommand
When using asynchronous SqlCommand, be careful to set ConnectionString's asynchronous processing to true.
Class Program {static void Main (string[] args) {int A, B; Threadpool.getmaxthreads (out A, out B); Console.WriteLine ("Number of auxiliary threads" + A + "+" number of original I/O threads "+ b); String str = "server=.; database=test;uid=sa;pwd=123; Asynchronousprocessing=true"; SqlConnection conn = new SqlConnection (str); SqlCommand cmd = conn. CreateCommand (); Cmd.commandtext = "INSERT into the person VALUES (15, ' Guo Jia ', 22)"; Conn. Open (); Cmd. Beginexecutenonquery (New AsyncCallback (Endcallback), CMD); Thread.Sleep (1000); Threadpool.getavailablethreads (out A, out B); Console.WriteLine ("Number of existing worker threads" + A + "" + "number of existing I/O threads" + b); Console.WriteLine ("Main thread continues execution!"); Console.readkey (); } public static void Endcallback (IAsyncResult result) {Thread.Sleep (2000); SqlCommand cmd = result. AsyncState as SqlCommand; Get the Asynchronous incoming parameter Console.WriteLine ("Execute command successfully:" + Cmd.commandtext); Console.WriteLine ("This execution affects the number of rows is:" + cmd.) Endexecutenonquery (result)); Cmd. Connection.close (); } }
The output is as follows:
Thread pool asynchronous I/O thread < third >