Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

The problem of exchanging Asynchronous and synchronous functions in QT

2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)06/02 Report--

Synchronous function and asynchronous function

According to Microsoft's MSDN commentary:

(1) synchronous function: when a function is executed synchronously, it will not be returned immediately when the function is called, and will not be returned until all the things to be done by the function are done.

(2) Asynchronous function: if an asynchronous function is called, the function will return immediately, even though the operation task specified by the function has not been completed.

(3) what is the impact of calling the above two functions in one thread on the calling thread?

When a thread calls a synchronization function (for example, this function is used to complete the task of writing a file), if the function does not immediately complete the specified operation, the operation will cause the calling thread to hang (handing over the right to use CPU to the system and letting the system assign it to other threads), and will not return until the operation specified by the synchronization function is completed, which will eventually cause the calling thread to be rescheduled.

When a thread calls an asynchronous function (for example, the function is used to complete the task of writing a file), the function returns immediately, even though the specified task has not been completed, so that the thread executes the next statement of the asynchronous function without being suspended. So how is the work specified by the asynchronous function done? Of course it was done through another thread; so where did the new thread come from? It could be a newly created thread in an asynchronous function or a thread that is already ready in the system.

(4) how does a thread that calls an asynchronous function synchronize with the execution result of the asynchronous function?

To solve this problem, the calling thread needs to use a "wait function" to determine when the asynchronous function completes the specified task. So immediately after the thread calls the asynchronous function, a "wait function" is called to suspend the calling thread until the asynchronous function has performed all its operations before executing the next instruction in the thread.

Have we found an interesting place?! That is, we can use wait functions to encapsulate an asynchronously executed function into a synchronous function.

two。 Synchronous and asynchronous invocation

The operating system has become very sophisticated today, and threading is one of the masterpieces. The operating system divides the CPU processing time into many short time slices. The instructions of one thread are executed at time T1 and the instructions of the next thread are executed at time T2. Each thread executes in turn. As a result, it seems that all threads are advancing side by side. In this way, multiple threads can be created during programming and executed at the same time, and each thread can complete different tasks "in parallel".

In the single-threaded mode, the computer is a strictly von Neumann machine, when one piece of code calls another piece of code, it can only use synchronous call, and must wait for the code to return the result before the call can continue to execute. With the support of multithreading, asynchronous calls can be used, and the caller and the callee can belong to two different threads. After the caller starts the callee thread, it continues to execute the subsequent code without waiting for the other party to return the result. After the called party has finished its execution, it will inform the caller by some means that the result has come out, please deal with it as appropriate.

Some processes in the computer are time-consuming. When calling this processing code, if the caller stands there and waits, it will seriously affect the performance of the program. For example, if you need to open a file to read out the data after a program starts, and then carry out a series of initialization processing according to the data, the main window of the program will not be displayed for a long time, making users feel that the program does not come out for a long time. Too bad. The problem can be easily solved with asynchronous calls: the entire initialization process is put into a separate thread, and the main thread starts the thread and then goes down, allowing the main window to be displayed instantly. When the user stares at the window, the initialization is quietly completed behind the back. After the program begins to run steadily, you can continue to use this technique to improve the instantaneous response of human-computer interaction. When the user clicks the mouse, if the operation is more time-consuming, then clicking the mouse will not immediately react, the whole program appears to be very heavy. With the help of asynchronous calls to deal with time-consuming operations, let the main thread wait for the next message at any time, users feel easy and quick when they click the mouse, and they are sure to have a good impression of the software.

Asynchronous calls are particularly effective for processing data entered from outside. If the computer needs to obtain data from a low-speed device, followed by a lengthy data processing process, it is obviously not cost-effective to use synchronous calls: the computer first sends a request to the external device, and then waits for data input; after the external device sends data to the computer, it also waits for the computer to complete the data processing before issuing the next data request. Both sides have a waiting period, which lengthens the whole process. In fact, the computer can make the next data request before processing the data, and then process the data immediately. If data processing is faster than data acquisition, only the computer has to wait, and external equipment can collect data continuously. If the computer connects multiple input devices at the same time, it can take turns to send data requests to each device, and process the data sent by each device at any time, the whole system can maintain continuous high-speed operation. The key to programming is to assign the data request code and the data processing code to two different threads. The data processing code calls a data request asynchronous function and then processes the data at hand. When the next set of data arrives, the data processing thread is notified, ends the wait state, makes the next data request, and then continues to process the data.

In an asynchronous call, the caller does not wait for the callee to return the result before turning away, so there must be a mechanism for the callee to notify the caller when the result is available. There are many means that can be used in the same process, and the most commonly used means are callbacks, event objects, and messages.

Callback: the callback method is simple: put a function address in the parameter when calling the asynchronous function, and the asynchronous function saves this address. When the result is available, the callback function can notify the caller. If you wrap an asynchronous function in an object, you can replace the callback function address with an event and notify the caller through the event handling routine.

Event: event is a common synchronization object provided by the Windows system to align steps between different threads in asynchronous processing. If the caller has nothing to do for the time being, you can call the wait function and so on, while the event is in the nonsignaled state. When the callee gives the result, the event object is placed in the signaled state, and the wait function automatically ends waiting, causing the caller to act again and retrieve the processing result from the callee. This method is more complex and slower than the callback method, but it has a lot of flexibility and can come up with a lot of tricks to adapt to the more complex processing system.

Message: sending notifications with Windows messages is a good choice, which is simple and secure. A user message is defined in the program, and the caller prepares the message handling routine. Immediately after the result comes out, the callee sends this message to the caller, and sends the result through the parameters WParam and LParam. Messages are always associated with a window handle, so callers must rely on a window to receive messages, which is an inconvenience. In addition, the speed will be affected by message contact, and callback is more advantageous when high-speed processing is needed.

If the caller and the callee belong to two different processes, due to the gap in memory space, it is generally simple and reliable to use Windows messages to send notifications, and the callee can transmit data to the caller with the help of the message itself. Event objects can also be shared among different processes by name, but they can only be notified and cannot transfer data by themselves, so they need memory sharing means such as Windows messages and FileMapping or communication means such as MailSlot and Pipe.

The principle of asynchronous invocation is not complicated, but it is easy to cause inexplicable problems in practical use, especially when different threads share code or data. It is necessary to pay attention to the existence of such sharing when programming, and avoid conflicts through a variety of status flags. The mutex object provided by the Windows system is particularly convenient to use here. Mutex can only have one administrator at a time. After one thread renounces jurisdiction, another thread can take over. When a thread takes over mutex before it reaches the sensitive area, other threads are blocked by the wait function; immediately after leaving the sensitive area, give up jurisdiction, so that the wait function ends waiting, and another thread has a chance to visit this sensitive area. This can effectively prevent multiple threads from entering the same sensitive area.

Because asynchronous invocation is prone to problems, it takes more design experience to design a safe and efficient programming solution, so it is best not to abuse asynchronous invocation. After all, synchronous calls are more comfortable: no matter where the program goes, you can figure it out as long as you stare at the moving point, and you don't always have the feeling of being attacked and nervous like asynchronous calls. You can even convert asynchronous functions to synchronous functions if necessary. The method is simple: immediately after calling the asynchronous function, call the wait function, wait there, wait until the asynchronous function returns the result, and then move on.

If the callback function contains slow processing such as file processing, the caller cannot wait, and you need to change the synchronous call to an asynchronous call to start a separate thread, then execute the subsequent code immediately, and let the thread do the rest slowly. An alternative method is to send an asynchronous message through the API function PostMessage, and then execute the subsequent code immediately. This is much easier and safer than building your own thread.

If your server has a large number of clients, your server will use asynchronous, but your client can use synchronous, the client generally has a single function, and can only perform the following work after receiving the data, so make it synchronous and wait there.

First, give an example of making a phone call:

Blocking block means that you dial someone's phone, but that person is not there, so you hold the phone and wait for him to come back, during which you can no longer use the phone. Synchronization is about the same as blocking.

Non-blocking nonblock means that you dial someone's phone, but that person is not here, so you hang up and call back later. As for whether he will come back or not, we will not know until he makes a phone call. The so-called "polling / poll".

Asynchronism means that you dial someone's phone, but that person is not there, so you ask the person who answered the phone to tell that person (leave a message) and call you when you get back (call back).

Synchronous asynchrony and blocking and non-blocking are two different concepts.

Synchronous asynchronism refers to communication mode, while blocking and non-blocking refers to whether to wait for the action to complete before returning when receiving and sending.

The first is the synchronization of communication, which mainly means that after the client sends the request, it must send the next request after the server has a response. So all requests at this time will be synchronized on the server side.

The second is the asynchronism of communication, which means that after sending a request, the client can send the next request without waiting for a response from the server, so that all the request actions will be asynchronous on the server side. The link of this request is like a request queue, and all actions will not be synchronized here.

Blocking and non-blocking are only applied to the reading and sending of requests.

In the process of implementation, if the server is asynchronous and the client is asynchronous, the communication efficiency will be very high, but if the server also returns to the requested link, the client can be synchronized. In this case, the server is compatible with synchronous and asynchronous. On the contrary, it will not be a problem if the client is asynchronous and the server is synchronous, but the processing efficiency is a little less efficient.

Imagine that you are a PE teacher and you need to test the 400 meters of 100 students. Of course you won't let 100 students start together, because when the students return to the finish line, you won't have time to pinch the meter to record their grades.

If you let one classmate start every time and wait for him to return to the finish line, you write down the score and then let the next one start until all the students have finished running. Congratulations, you have mastered the synchronous blocking mode. You design a function that passes in the student number and the start time, and the return value is the time to reach the finish line. You can complete the test task by calling the function 100 times. This function is synchronous because as long as you call it, you can get the result; this function is also blocked, because once you call it, you have to wait until it gives you the result and can't do anything else.

If you let a classmate start every 10 seconds until all the students have finished, and on the other side, every time a student comes back to the finish line, record the result until all the students have finished running. Congratulations, you have mastered the asynchronous non-blocking mode. You have designed two functions, one of which records the start time and student number, which you will call actively 100 times; the other function records the arrival time and student number, this function is an event-driven callback function, when a student arrives at the destination, you will call passively. The function you call actively is asynchronous, because when you call it, it doesn't tell you the result; the function is also non-blocking, because once you call it, it returns immediately, and you don't have to wait to call it again. But only call this function 100 times, you did not complete your test task, you also need to passively wait for another function to be called 100 times.

Of course, you will soon realize that the efficiency of synchronous blocking mode is significantly lower than that of asynchronous non-blocking mode. So, who else uses synchronous blocking mode? Yes, asynchronous mode is efficient, but it is more troublesome. While you record the data of your starting classmates, you have to record the data of arriving classmates, and the order in which the students go back to the finish line is not the same as the order in which they start. So you have to keep looking up the student number in your grade book. In a hurry, you tend to get the wrong guy. You may come up with a smarter idea: you bring a lot of stopwatches and let your classmates test each other in groups. Congratulations! You have mastered the multithreaded synchronization mode!

Each student with a stopwatch can call your synchronization function independently, so it is not easy to make mistakes, and the efficiency is greatly improved. as long as there are enough stopwatches, the efficiency of synchronization can reach or even exceed asynchronism.

Understandably, your question may be: since multithreaded synchronization is fast and good, is it necessary for asynchronous mode to exist?

Unfortunately, asynchronous mode is still very important, because in many cases, you don't have a lot of stopwatches. The peer-to-peer system that you need to communicate may only allow you to establish a SOCKET connection, as is required by many large business systems in the financial and telecommunications industries.

I. synchronous blocking mode

In this pattern, the user-space application executes a system call and blocks until the system call completes (data transfer completes or an error occurs).

Second, synchronous non-blocking mode

A slightly less efficient way of synchronously blocking IBO. The non-blocking implementation is that the Istroke O command may not be satisfied immediately and requires the application to call it many times to wait for the operation to complete. This may be inefficient because in many cases, when the kernel executes this command, the application must be busy waiting until the data is available, or trying to perform other work. Because the data becomes available in the kernel, there is a gap between the data returned by the user calling read, which results in a decrease in the overall data throughput. However, asynchronous non-blocking is still efficient because it is multithreaded.

/ * create the connection by socket * means that connect "sockfd" to "server_addr" * synchronous blocking mode * / if (connect (sockfd, (struct sockaddr *) & server_addr, sizeof (struct sockaddr)) =-1) {perror ("connect"); exit (1);} / * synchronous non-blocking mode * / while (send (sockfd, snd_buf, sizeof (snd_buf), MSG_DONTWAIT) =-1) {sleep (1); printf ("sleep\ n");}

Network program development process:

1. Demand analysis

two。 Design the packet according to the requirements (generally divided into two parts: the packet header and the packet data, the packet header is used to store the necessary information of the packet, such as information type, data length, etc.)

3. Define the transport protocol (how to transmit it).

4. Understand requirements, design overall architecture, use design patterns and other methods to analyze problems and design class diagrams.

5. To implement, it is usually necessary to cooperate with multithreading to realize the communication problem. There are generally waiting for customer request thread, receiving data thread, sending data thread, resource cleaning thread.

6. Realize the server side.

7. Implement the client.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 257

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report