Summary of. Net concurrent asynchronous Processing

Source: Internet
Author: User

When processing a lot of IO logic or thinking about background computing, we will use concurrency. There are two types of concurrency: computing-intensive and IO-intensive.

1.Computing-intensive:
If we regard the processing in the thread as a task, computing-intensive means that this task is mainly used to process computing and logic. In other words, it is mainly used to consume CPU. A typical computing-intensive scenario is to perform some time-consuming computing on the client background to prevent the interface from being suspended. Concurrent processing of computing-intensive tasks, in addition to avoiding some thread congestion (for example, the interface is suspended), but also to make full use of CPU resources, the current PC and notebook are generally dual-core or 4-core, the server may have several CPUs, so that concurrent execution can allow the computer to execute multiple tasks at the same time.

2.IO-intensive: IO-intensive tasks generally process a large number of IO operations. Of course, I/O-intensive tasks that only contain one I/O operation can also be considered as IO-intensive tasks because IO operations are generally time-consuming. IO-intensive scenarios include reading multiple files or requesting multiple WebServices. The concurrent execution of I/O tasks has more advantages, mainly to save CPU resources and speed up processing. Because many IO operations are time-consuming, but they basically do not use the CPU, if we use a single thread for processing, the CPU may be in a blocking state for a long time, this is a waste of CPU resources. At the same time, a single thread can only execute IO operations one by one, and the time will also be longer.

The following uses a few simple examples to introduce how to use the thread pool and Asynchronization in. Net to implement concurrency (you can also directly create a thread on the same day ).

1.The most common example is single-task computing-intensive.:

Add a computing-intensive task to the thread pool. The thread pool executes the task when the thread is idle:

        private static void Sample2()
{
ThreadPool.QueueUserWorkItem(count => Run((int)count), 20);
}

private static void Run(int count)
{
for (int i = 0; i < count; ++i)
{
Console.WriteLine(i);
Thread.Sleep(100);
}
Console.WriteLine("finished");
}

The preceding Run can have any parameter combination delegate, but the method that can add QueueUserWorkItem can only contain one object parameter. A parameter class needs to be packaged and then decomposed in lambda and passed to Run, you can also use a dictionary as a parameter class. If you need to do some processing when the computation is complete, you can use the following Asynchronous Method.

 

Private static void Sample1 ()
{
Action <int> a = c =>
{
Run (c );
};

// Perform the operation asynchronously. Call EndInvoke in Callback,
// Otherwise, resource leakage may occur.
A. BeginInvoke (20, ar =>
{
A. EndInvoke (ar );
}, Null );
}

The code that completes the processing can be followed by a. EndInvoke (ar. Note: It is best to call EndInvoke in the event of disconnection, otherwise it may cause resource leakage or some memory cannot be recycled.

 

2.In this example, I want to asynchronously read a file, add a row number, and print it.:
In this way, the CPU can be empty for other tasks during the IO operation of File Reading.

Public class AddLineNum
{
/// <Summary>
/// Read the file asynchronously and add the row number to display it
///
/// There are three steps in total:
/// 1. Prepare for the task, start reading the file, and run it in the current thread.
/// 2. asynchronous file reading. This step does not occupy threads and CPU resources.
/// 3. Read data processing and display, and execute in the third thread
/// </Summary>
/// <Param name = "file"> </param>
Public AddLineNum (string file)
{
_ File = file;
}

/// <Summary>
/// 1. Start reading the file
/// </Summary>
Public void Begin ()
{
Long fileSize = new FileInfo (_ file). Length;
_ Buffer = new byte [fileSize];
FileStream reader = File. OpenRead (_ file );
Reader. BeginRead (_ buffer, 0, (int) fileSize, ar =>
{
Int count = reader. EndRead (ar );
Console. WriteLine ("Read length: {0}", count );
End (); // process read data
}, Null );
}

/// <Summary>
/// 2. process read data
/// </Summary>
Private void End ()
{
String text = Encoding. UTF8.GetString (_ buffer );
String [] lines = text. Split (new string [] {Environment. NewLine}, StringSplitOptions. RemoveEmptyEntries );
For (int I = 0; I <lines. Length; ++ I)
{
Console. WriteLine (String. Format ("{0 }:{ 1}", I, lines [I]);
}
}

Private string _ file = "";
Private byte [] _ buffer = null;
}

Call code:

     AddLineNum apmOne = new AddLineNum("AddLineNum.cs");
apmOne.Begin();

As mentioned in the comment, asynchronous processing does not occupy the CPU when processing file reads.

3.In this example, multiple web requests are initiated at the same time, and the results are summarized at the end of all requests..

Public class CheckSiteStatus
{
Public CheckSiteStatus (IList <string> sites)
{
_ Sites = sites;
}

Public void Begin ()
{
_ FinishedCount = _ sites. Count;
Foreach (string site in _ sites)
{
HttpWebRequest req = (HttpWebRequest) HttpWebRequest. Create ("http: //" + site );
Req. Method = "HEAD ";
Req. BeginGetResponse (ar =>
{
HttpWebRequest request = ar. AsyncState as HttpWebRequest;
Try
{
HttpWebResponse res = (HttpWebResponse) (request. EndGetResponse (ar ));
_ StatusDic [request. RequestUri. Host] = res. StatusCode;
}
Catch (WebException exp)
{
HttpWebResponse errRes = exp. Response as HttpWebResponse;
If (errRes! = Null)
{
_ StatusDic [request. RequestUri. Host] = errRes. StatusCode;
}
Else
{
_ StatusDic [request. RequestUri. Host] = HttpStatusCode. NotFound;
}
}

// Complete one
Interlocked. Decrement (ref _ finishedCount );
If (_ finishedCount <= 0)
End ();
}, Req );
}
}

Private void End ()
{
Int goodCount = 0;
Foreach (var pair in _ statusDic)
{
If (pair. Value = HttpStatusCode. OK)
{
++ GoodCount;
}
Console. WriteLine ("site: {0}, status: {1}", pair. Key, pair. Value );
}

Console. WriteLine ("{0} of {1} can be connected.", goodCount, _ statusDic. Keys. Count );
}

Private Dictionary <string, HttpStatusCode> _ statusDic = new Dictionary <string, HttpStatusCode> ();
Private IList <string> _ sites;
Private int _ finishedCount = 0;
}

Call code:

        CheckSiteStatus checker = new CheckSiteStatus(new string[] {
"www.baidu.com",
"www.google.com",
"www.soso.com",
"www.idiot.com/"
});
checker.Begin();

In this example, we use _ finishedCount to track the number of executions completed, and then use Interlocked to implement synchronization control.

 

4.Similar to the functions implemented in Example 3 above, the main thread blocks and wastes some CPU resources, but the code is more concise and clear.

Class CheckSiteStatus2
{
Public static void Check (IList <string> sites)
{
// Start the request
Dictionary <string, HttpWebRequest> reqs = new Dictionary <string, HttpWebRequest> ();
Dictionary <string, IAsyncResult> asyncs = new Dictionary <string, IAsyncResult> ();
Foreach (string site in sites)
{
HttpWebRequest req = (HttpWebRequest) HttpWebRequest. Create ("http: //" + site );
Req. Method = "HEAD ";
Reqs [site] = req;
Asyncs [site] = req. BeginGetResponse (null, null );
}

//: End the request and update the status.
Dictionary <string, HttpStatusCode> statusDic = new Dictionary <string, HttpStatusCode> ();
Foreach (var pair in asyncs)
{
HttpWebRequest request = reqs [pair. Key];
Try
{
HttpWebResponse res = (HttpWebResponse) (request. EndGetResponse (pair. Value ));
StatusDic [request. RequestUri. Host] = res. StatusCode;
}
Catch (WebException exp)
{
HttpWebResponse errRes = exp. Response as HttpWebResponse;
If (errRes! = Null)
{
StatusDic [request. RequestUri. Host] = errRes. StatusCode;
}
Else
{
StatusDic [request. RequestUri. Host] = HttpStatusCode. NotFound;
}
}
}

//: Summary when all processing is complete
Int goodCount = 0;
Foreach (var pair in statusDic)
{
If (pair. Value = HttpStatusCode. OK)
{
++ GoodCount;
}
Console. WriteLine ("site: {0}, status: {1}", pair. Key, pair. Value );
}

Console. WriteLine ("{0} of {1} can be connected.", goodCount, statusDic. Keys. Count );
}
}

Call code:

CheckSiteStatus2.Check(new string[] {
"www.baidu.com",
"www.google.com",
"www.soso.com",
"www.idiot.com/"
});


The above code is directly implemented in a static method, and the steps are also clear.
 

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.