[Switch from jeffreyzhao] correct use of asynchronous operations

Source: Internet
Author: User
I wanted to write a topic about asynchronous calls to LINQ to SQL, but before that, I 'd like to write an article Article To elaborate on some principles for using asynchronous operations to avoid misuse of some friends. Program Performance is reduced. This article will discuss in. net, aiming at clarifying concepts and avoiding misuse, and finally proposing common Asynchronous Operation scenarios and use cases. In this way, we can know when to use asynchronous operations, and when it will be worth the candle.

Let's first confirm a concept, that is, "Thread ". Note that, unless otherwise stated, the "Thread" mentioned in this Article refers to the managed thread in the CLR thread pool, which is similar to the windows thread or fiber thread (fiber) it is not the same concept. Similarly, it is not an instance of the system. Thread class. To put it simply, it is a unit of work execution managed by CLR. Whenever a task needs to be executed, the CLR assigns such an execution unit to work. When all threads in the thread pool are used up, they cannot execute new tasks. A managed thread is released after the task is completed. The thread pool itself is an "Object pool" that will be created when a new object (managed thread) is required, after the object is not needed (no new tasks need to be assigned a hosting thread within a certain period of time), the owner is responsible for destroying and releasing resources. As for the number of threads in the thread pool, in versions earlier than CLR 2.0 SP1, the number of CPUs is * 25, but since CLR 2.0 SP1, the number of CPUs is * 250. However, the threads in the thread pool are limited, so we must use it properly.

Previously, a computer had only one CPU, and theoretically only one task can be executed at the same time. Today's hyper-threading, multi-core, and even real multiple CPUs allow computers to run multiple tasks at the same time. One important feature of multi-threaded programming is the ability to make full use of the computing power of the CPU to complete a task faster. Obviously, if a very large computing task is completed by only one thread, only one CPU can be involved in the calculation. However, if you split a large task into multiple sub-tasks that do not affect each other, it will take less time to allow multiple CPUs to participate in the operation at the same time. If the purpose of an operation is to perform a large number of operations, or the operation that requires a large amount of time, we call it "compute-bound operation", that is, the operation restricted by the computing capability.

The opposite of "compute-bound operation" is "io-bound operation ". "Io-bound operation" refers to operations that require a lot of time on Io to complete such a task due to external constraints. For example, you can read a file or request a resource on the network. For this operation, there are more computing threads, and the computing power is no longer powerful, because the task is limited by hard disk, network, and other IO devices. For Io-bound operation, all we can do is "wait ".

For "synchronization operations", "waiting" means "blocking", and a thread will "idle" until the operation is completed. This method may cause various problems in many cases, so "asynchronous operations" occur, but it is also "asynchronous operations", different tasks, and different situations, the solution to the problem is different from the solution. The following describes the content through examples in my life:

Zhao's friends opened a restaurant and invited 10 staff members. Recently, the friend often complained to Lao Zhao that there was always not enough staff to greet them when there were many guests. When Zhao asked, he learned that the restaurant had a special way of working: When a guest came to dinner, there would be a staff member who greeted the restaurant with warm reception. When the guests ordered the dishes, the staff will go to the kitchen to cook in person-yes, that's it-after the work is done, the staff will bring the food to the guests and then entertain other guests. It often takes a long time to cook food. In some cases, all the staff are in the kitchen, but no one can order food. So Lao Zhao gave his friend an idea: let a few staff members serve as waiters, only to greet the guests, and the rest are chefs who have been working in the kitchen. After the guests order their food, the waiter will tell the cook about their requirements. The cook starts to work, and the waiter will be able to greet other guests. My friend had an epiphany and the problem was solved.

Of course, in the story above, Old Zhao's friends are too stupid. restaurant owners in real life will not make such low-level mistakes in personnel scheduling. The development of a client application is often similar to the above. When running a program, the UI thread (waiter) is responsible for displaying the interface (entertaining guests). After the user operates the application (ordering, the UI thread can use synchronous operations to perform operations (the waiter cooks in person), but if this is a long time compute-bound operation (cooking is a long time-consuming operation ), the interface cannot be re-painted or responded to user requests (Guests cannot be entertained), so the user experience of such applications is naturally poor (customers feel that the service quality is low ). However, as long as the UI thread uses asynchronous operations (notify the cook), let another thread (another worker) perform operations, the UI thread can continue to be responsible for UI re-painting or other user operations (to entertain other guests.

In this case, asynchronous operations do not improve the computing capability or save resources (or require the work of a person), but provide a good user experience. But how can we use asynchronous operations? In actual development, we can use the delegated begininvoke for asynchronous calls.

The following example corresponds to another situation:

Old Zhao's restaurant-opening friend plans to open another fast food restaurant after earning a small sum. The difference between a fast food restaurant and a restaurant is that most of the food produced by a fast food restaurant is processed by machines. Unfortunately, in this case, the friend still encountered a problem: there are more than enough machines, but there are still not enough people. The current practice is still quite unscientific: After the waiter knows what food the guest needs, the waiter inserts the raw material into the machine and looks at how the machine turns the raw material into delicious food. After the work of the machine is completed, the waiter packs and sends the food and continues to entertain other guests. After hearing this, Lao Zhao still had to laugh and cry: Why can't the waiter entertain other guests while the machine is working?

This example corresponds to an ASP. NET application. In ASP. in net, each request (guest) will use a thread (waiter) in the thread pool to process (entertain). In the process, it is likely that you need to access the database (use the machine). For common practices, the processing thread will wait for the database operation to return (The waiter looks at the machine until the operation is completed ). For the web server, this is probably a long io-bound operation. If the thread is blocked for a long time, it is likely to reduce the performance of the Web application, because after the threads in the thread pool are used up (the waiters all go to the stove), they will not be able to process new requests (no one will entertain the guests ). If we can allow the thread to process other requests (entertain other guests) when the database performs a long query operation ). In this way, we only need to continue processing (packaging) after the database operation is complete and send the data to the client (sending.

This is the method for processing io-bound operation. Obviously, this is also an asynchronous operation. When we want to implement an asynchronous io-bound operation, CLR will (via Windows API) issue an IRP (I/O Request Packet ). When the device is ready, it will find and process an IRP (for example, a request to read the data closest to the current head) that is "most desired, after the processing is completed, the device returns an IRP indicating that the work is completed (via Windows. CLR creates an iocp (I/O completion port) for each process and maintains it with the Windows operating system. Once the completed IRP is put into the iocp (completed through the internal threadpool. bindhandle), the CLR will allocate an available thread as soon as possible to continue the next task.

This method requires an important condition, that is, the operation that sends the request IRP can return immediately, and this Io operation will not use any thread. At this time, this asynchronous call is actually saving resources, because we can free up the thread to process other tasks, which is the biggest difference from the first asynchronous call. However, it is a pity that this practice obviously requires the support of the operating system and equipment, that is, only specific operations can enjoy these benefits. So what operations in. NET Framework can make profits?

    • filestream operation: beginread and beginwrite. An Asynchronous Operation is initiated when beginread/beginwrite is called, but fileoptions is passed in only when filestream is created. the asynchronous parameter can be used to obtain real iocp support. Otherwise, the beginxxx method will use the implementation defined on the stream base class by default. In the stream base class, the beginxxx method uses the delegated begininvoke method to initiate an asynchronous call-this will use an additional thread to execute the task. Although the current call thread returns immediately, data reading or writing operations still occupy another thread (asynchronous operations supported by iocp do not require threads ), therefore, there is no "save", but it is likely to reduce the performance of the application, because additional thread switching will cause performance loss.
    • DNS operation: begingethostbyname and beginresolve.
    • socket operation: beginaccept, beginconnect, and beginreceive.
    • webrequest operation: begingetrequeststream and begingetresponse.
    • sqlcommand operation: beginexecutereader, beginexecutenonquery, and so on. This may be the most common Asynchronous Operation for developing a web application. If you need to obtain iocp support for database operations, you need to mark asynchronous processing as true (false by default) in the connection string. Otherwise, an exception is thrown when the beginxxx operation is called.
    • webservcie call operation: for example, the beginxxx method in. NET 2.0 or the Web Service proxy generated by WCF, And the invokeasync method of clientbase In WCF.

One thing I want to emphasize is that the entrusted begininvoke method does not support iocp. This will use an additional thread to execute tasks, which will not only reduce the cost, but also reduce the performance. It may be worth noting that iocp does not occupy threads, but a real asynchronous operation cannot be destroyed in ourCode. For example, I have seen the following code:

SqlcommandCommand;

IasyncresultAR = command. beginexecutenonquery ();
IntResult = command. endexecutenonquery (AR );

Although the beginexecutenonquery method is indeed supported by iocp, the later called endexecutenonquery will block the current thread until the database operation returns-asynchronous operations are not used in this way. As for the correct practice, there have been many articles on the Internet about how to use ASP. net correctly uses asynchronous operations. You can search for the relevant information, and I will also mention it in future articles.

For asynchronous operations, let's talk about it this time.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.