. NET Server development-multi-thread usage Summary (multi-thread usage knowledge),. net Summary

Source: Internet
Author: User

. NET Server development-multi-thread usage Summary (multi-thread usage knowledge),. net Summary

I haven't updated my blog for a while. I 've been writing a book in the last six months 《. NET Framework Design-large enterprise-level framework design art. I'm glad that this book will be published by the Turing publishing house in October, I will introduce this book in another article when the book is to be published. Let us first reveal that this book is a summary of the application framework learning by bloggers over the years. It contains more than a dozen heavyweight framework models that are frequently used at present, this is a good reference for learning frameworks and framework development.

Now, go to the topic of the article.

I have been engaged in SOA service development for the past few months. Simply put, I provide service interfaces, from providing front-end interface WEBAPI to providing backend interface WCF \ SOAFramework, during this period, I learned a lot about multithreading. Some of these experiences are my own experiences after incorrect use, and some are the advice of my predecessors, in short, you will not realize how to use these things, so I think it is necessary to sum up and share them with other bloggers who work on the front line like me.

We will introduce the order of Service Processing:

1. Use the entry thread to process long-time calls:

Any service call must first go to the service entry method. This method usually acts as the facade interface of the domain logic (Division of service interfaces by using system cases ), use Cases are called through this interface. When we need to deal with a long process, we will face a headache for timeout exceptions. If we design how to make timeout compensation measures, it will be very complicated and there is no necessary overhead. Service calling scenarios with long-term processing are mostly used to synchronize data through a JobWs (Work Service) on a regular basis (I learned in this process ), when we cannot predict how long our service will process, we will basically set the connection timeout time of the caller first (will this happen ?); This is normal, and the timeout is used for us. However, we ignore our current business scenario, if your service does not return any status values, "In fact, you should enable an independent thread to process the synchronization logic, so that service callers can receive the corresponding values as soon as possible ".

1 public class ProductApplicationService 2 {3 public void SyncProducts () 4 {5 Task. factory. startNew () => 6 {7 var productColl = DominModel. products. getActivateProducts (); 8 if (! ProductColl. Any () return; 9 10 DominModel. Products. WriteProudcts (productColl); 11}); 12} 13}View Code

In this way, the caller can be liberated as soon as possible. by enabling a separate thread, the caller can process the specific synchronization logic.

What if your service needs to return a status value? In fact, we can refer to the "Asynchronous Message architecture mode" to write messages to a message queue, and then the client can periodically retrieve or push messages, the current service method can be smoothly processed, at least contributing to the overall performance bottleneck of the system.

1.1 exception handling:

The entry Location usually records the call exception information, that is, a try {} catch {} is added to capture all the exception information of this call. (Of course, you may say that the Code is full of try {} catch {}, which is not very good. You can put it in an invisible place for automatic processing. This is good or bad, configuration is indispensable for the invisible part, and the configuration of custom exception types is indispensable. In short, everything has two sides .)

1 public class ProductApplicationService 2 {3 public void SyncProducts () 4 {5 try 6 {7 Task. factory. startNew () => 8 {9 var productColl = DominModel. products. getActivateProducts (); 10 if (! ProductColl. any () return; 11 12 DominModel. products. writeProudcts (productColl); 13}); 14} 15 catch (Exception exception) 16 {17 // record down... 18} 19} 20}View Code

Like this, it seems that there is no problem, but if we look at it carefully, we will find that this try {} catch {} cannot catch any of our exception information, because this method is outside the thread we opened, that is to say, it has long ended. The root of the enabled thread processing stack does not have any try {} catch {} mechanism code; so we need to slightly adjust the synchronization code to support exception capture.

1 public class ProductApplicationService 2 {3 public void SyncProducts () 4 {5 Task. factory. startNew (SyncPrdoctsTask); 6} 7 8 private static void SyncPrdoctsTask () 9 {10 try11 {12 var productColl = DominModel. products. getActivateProducts (); 13 if (! ProductColl. any () return; 14 15 DominModel. products. writeProudcts (productColl); 16} 17 catch (Exception exception) 18 {19 // record down... 20} 21} 22}View Code

If you have installed a secondary plug-in such as Resharp, it will be very helpful for you to refactor the code, and extracting a method will be very convenient and fast;

The above Code contains the exception capture code in the new thread. This will not cause your program to throw many unprocessed exceptions and may lose data in important logic points. It doesn't mean that all exceptions should be handled by the framework. We need to manually control the exceptions of a logic point so that we can ensure that our own logic can continue to run. Some logics cannot terminate the entire processing process due to exceptions.

2. Improve the reading of multiple groups of data using parallel processing

When a service interface is located at the outermost layer of the SOA service, it usually needs to wrap numerous internal service interfaces to combine the data required by the outside. In this case, you need to query the data of many interfaces, then, wait until all the data arrives and return it to the front-end. Since I have provided interfaces to the front-end H5 for a while, what impressed me most is that the Service Interface needs to integrate all the data to the front-end, from the user's point of view, I don't want the mobile phone interface to be asynchronous. After all, there is still white space on the screen. However, this demand poses a problem for our developers. If we combine the data by reading the data in sequence, that time is unacceptable, therefore, we need to enable parallelism to read data from multiple backend service interfaces at the same time (provided that the data is not dependent on each other ).

1 public static ProductCollection GetProductByIds (List <long> pIds) 2 {3 var result = new ProductCollection (); 4 5 Parallel. forEach (pIds, id => 6 {7 // parallel method 8}); 9 10 return result; 11}View Code

Everything looks comfortable. Multiple IDs are run together at the same time, but there is a pitfall.

2.1 control the number of parallel threads:

If we use the preceding code to enable parallel processing, everything will go smoothly from the GetProductByIds business point, and the effect will be obvious and fast; however, if you initiate another service call when the GetProductByIds method is still being processed, you will find that the server response slows down because all request threads are occupied, here, Parallel is not as intelligent as we think. We can control the number of threads based on the actual situation. We need to control the maximum number of threads in our Parallel run, this prevents other subsequent requests in the service queue due to the use of multiple threads by a service point (the CPU is not necessarily high at this time. If the CPU is too high, the request is not accepted, however, it is also possible that the number of threads is insufficient due to system settings)

1 public static ProductCollection GetProductByIds (List <long> pIds) 2 {3 var result = new ProductCollection (); 4 5 Parallel. forEach (pIds, new ParallelOptions () {MaxDegreeOfParallelism = 5/* set the maximum number of threads */}, id => 6 {7 // parallel method 8 }); 9 10 return result; 11}View Code2.2 the first principle is the sequence before and after data is processed in parallel.

I made two mistakes at this point. For the first time, I disrupted the Data Order required by the front-end, leading to data ranking problems; the second attempt is to disrupt the synchronization time of data written to the database. As a result, the program cannot continue the synchronization at the last end time. Therefore, you must remember that when you use parallel operations, you must first ask yourself that your current data context logic does not care about the sequential relationship between the two. Once the parallel operation is enabled, all the data is unnecessary.

3. manually enable a thread to replace the thread started by the parallel Library

Now we provide more or less service interfaces that use Asynchronous async, probably to allow our system to mention the concurrency, this allows valuable request processing threads to be reused by the system in a timely manner instead of being wasted on waiting.

The code will probably look like this. service entry:

1 public async Task <int> OperationProduct (long ids) 2 {3 return await DominModel. Products. OperationProduct (ids); 4}View Code

Business logic:

1 public static async Task <int> OperationProduct (long ids) 2 {3 return await Task. factory. startNew <int> () => 4 {5 System. threading. thread. sleep (5000); 6 return 100; 7 8 // In fact, the thread enabled here is the request processing thread in the request thread pool. To put it bluntly, this will not increase the concurrency. 9}); 10}View Code

In fact, when we finally open a new thread, this new thread is of the same type as your awit thread. This will not improve concurrency, but will affect performance due to frequent thread switching. To make your async meaningful, manually enable the new thread to improve concurrency. (The premise is that you understand the ratio of the overall CPU to the thread of the current system. That is to say, you can enable one or two manual threads, but you need to place it on the concurrent entry, so proceed with caution)

It is a little troublesome to enable the manual thread in the Task. Check the Code:

1 public async Task <int> OperationProduct (long id) 2 {3 var funResult = new AWaitTaskResultValues <int> (); 4 return await DominModel. products. operationProduct (id, funResult); 5} 6 7 public static Task <int> OperationProduct (long id, AWaitTaskResultValues <int> result) 8 {9 var taskMock = new Task <int> () => {return 0 ;}); // It is just an await simulation object, this mainly allows the system to reclaim the current "request processing thread" 10 11 var Thread = new thread (threadIds) => 12 {13 Thread. sleep (7000); 14 15 result. resultValue = 100; 16 17 taskMock. start (); // since there is no logic, the processing will be completed soon. 18}); 19 20 thread. Start (); 21 22 return taskMock; 23}View Code

The reason for this problem is to let the system release the await thread rather than blocking the thread. Through a simple test, I can use a small number of threads to process more concurrent requests.

 

Author: Wang qingpei

Source: http://www.cnblogs.com/wangiqngpei557/

The copyright of this article is shared by the author and the blog Park. You are welcome to reprint this article. However, you must keep this statement without the author's consent and go to the Article Page.


It is important to develop a net website with multiple threads and sockets.

It is very important that there will be many unknown errors in network communication without multithreading. Once a problem occurs, the entire program will die...

Where is multithreading used for net?

If you can implement the following functions, you do not need to use multiple threads.
There are two buttons on a form,
The code function of button1 is to make the form text continuously loop, similar to the following code
Dim I As Integer
While True
Me. Text = I
I + = 1
End While
The code function of button2 is to pop up a dialog box after clicking.
If you can click 1 first and then 2, you don't feel stuck at all, and the text change of form is not interrupted, you don't need to use multiple threads.

Related Article

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.