(10) Asynchronous - what is asynchronous (1)

1. What is asynchronous

When a program is started, the system creates a new process in memory.

Process: A collection of resources that make up a running program. These resources include virtual address space, file handles, and many other things a program needs to run.

Inside a process, the system creates a kernel object called a thread, which represents the actual executing program. (Thread is short for "thread of execution.") Once the process is established, the system begins execution of the thread at the first statement of the Main method.

About threads:

  • By default, a process contains only one thread (the main thread), which executes from the beginning to the end of the program.
  • Threads can spawn other threads (child threads), so at any point in time a process may contain multiple threads in different states executing different parts of the program.
  • If a process has multiple threads, they will share the resources of the process.
  • The unit that the system schedules for processor execution is the thread, not a process.

Example of not using asynchronous:
On my computer, in the example in the book CountCharacters(1, “htttp://microsoft.com” ); Calling the DownloadString method in the method will be stuck for a long time, and it may be passed to the server of Microsoft’s official website has a problem. (According to my experience, Microsoft's official website calls the loading step at certain times and it often becomes very slow, especially when logging in to a Microsoft account, it is more obvious) So I directly changed the address of Baidu's homepage to test .

 class MyDownloadString
    {
        Stopwatch sw = new Stopwatch();
        const int LargeNumber = 6000000;

        public void DoRun()
        {
            sw.Start();
            int t1 = CountCharacters(1, "https://www.baidu.com/");
            int t2 = CountCharacters(2, "http://www.illustratedcsharp.com");
            CountToALargeNumber(1);
            CountToALargeNumber(2);
            CountToALargeNumber(3);
            CountToALargeNumber(4);
            Console.WriteLine($"Chars in https://www.baidu.com/   :{t1}");
            Console.WriteLine($"Chars in http://www.illustractedcsharp.com   :{t2}");
        }

        //获取网页源代码内容的长度
        private int CountCharacters(int id,string uriString)
        {
            WebClient wc1 = new WebClient();
            //执行此处记录下时间值
            Console.WriteLine("Starting call {0}   :  {1, 4:N0} ms",
                id, sw.Elapsed.TotalMilliseconds);
            //需要时间下载并获取网页源代码
            string result = wc1.DownloadString(new Uri(uriString));
            Console.WriteLine("  Call {0} completed:    {1, 4:N0}ms",
                id, sw.Elapsed.TotalMilliseconds);

            return result.Length;
        }

        //每间隔一次时间,打印结果。
        //该方法在书上是有两个形参的,
        //但是我觉得有些多余(可能作者为了使代码规范化吧)
        //我为了简便就只使用一个形参
        private void CountToALargeNumber(int id)
        {
            //循环作用:为了让程序执行一段时间,才打印一次结果,以方便查看计数值
            //如果不执行循环,以下打印结果很可能都是相同值。
            for (long i = 0; i < LargeNumber; i++)
                ;

            Console.WriteLine("  End counting {0}  :   {1,  4:N0}ms",
                id, sw.Elapsed.TotalMilliseconds);
        }
    }
  
    class Program
    {
        static void Main(string[] args)
        {
            MyDownloadString ds = new MyDownloadString();
            ds.DoRun();

            Console.ReadKey();
        }
    }

Output result:

Starting call 1 : 1 ms
Call 1 completed: 694ms
Starting call 2 : 694 ms
Call 2 completed: 3,147ms
End counting 1 : 3,188ms
End counting 2 : 3,235ms
End counting 3 : 3,280ms
End counting 4 : 3,323ms
Chars in https://www.baidu.com/ :9269
Chars in http://www.illustractedcsharp.com :5164

It can be seen from the output results that when the DoRun method is executed, the codes in the method are executed in order. That is to say, before calling a line of code, you have to wait for the execution of the previous line of code before it can be executed. In the example here, since calling the DownloadString method needs to request network time, it is necessary to wait for the DownloadString method to complete before executing the next line of code.

Please add a picture description

Example using async

According to the above example, rewrite the CountCharacters method as an asynchronous calling method:
change DownloadString to DownloadStringTaskAsync, that is, change it to an asynchronous calling method.

      class MyDownloadString
    {
        Stopwatch sw = new Stopwatch();
        const int LargeNumber = 6000000;

        public void DoRun()
        {
            sw.Start();
            //此处代码修改
            Task<int> t1 =  CountCharacters(1, "https://www.baidu.com/");
            Task<int> t2 = CountCharacters(2, "http://www.illustratedcsharp.com");
            CountToALargeNumber(1);
            CountToALargeNumber(2);
            CountToALargeNumber(3);
            CountToALargeNumber(4);
            Console.WriteLine($"Chars in https://www.baidu.com/   :{t1.Result}");//此处代码修改
            Console.WriteLine($"Chars in http://www.illustractedcsharp.com   :{t2.Result}");//此处代码修改
        }

        //获取网页源代码内容的长度,此处代码修改
        private async Task<int> CountCharacters(int id, string uriString)
        {
            WebClient wc1 = new WebClient();
            //执行此处记录下时间值
            Console.WriteLine("Starting call {0}   :  {1, 4:N0} ms",
                id, sw.Elapsed.TotalMilliseconds);
            //需要时间下载并获取网页源代码

            var result = await wc1.DownloadStringTaskAsync(new Uri(uriString));//此处代码修改

            wc1.DownloadString(new Uri(uriString));

            Console.WriteLine("  Call {0} completed:    {1, 4:N0}ms",
                id, sw.Elapsed.TotalMilliseconds);

            return result.Length;
        }

        //每间隔一次时间,打印结果
        private void CountToALargeNumber(int id)
        {
            //循环作用:为了让程序执行一段四件,才打印一次结果,以方便查看计数值
            //如果不执行循环,以下打印结果很可能都是相同值。
            for (long i = 0; i < LargeNumber; i++)
                ;

            Console.WriteLine("  End counting {0}  :   {1,  4:N0}ms",
                id, sw.Elapsed.TotalMilliseconds);
        }
    }
  
    class Program
    {
        static void Main(string[] args)
        {
            MyDownloadString ds = new MyDownloadString();
            ds.DoRun();

            Console.ReadKey();
        }
    }

Output result:

Starting call 1 : 6 ms
Starting call 2 : 237 ms
End counting 1 : 287ms
End counting 2 : 342ms
Call 1 completed: 384ms
End counting 3 : 394ms
End counting 4 : 440ms
Chars in https://www.baidu.com/ :9269
Call 2 completed: 925ms
Chars in http://www.illustractedcsharp.com :5164

It can be seen from the output result that when the program executes to the DownloadStringTaskAsync method, the program is called asynchronously. This allows DownloadStringTaskAsync to be executed while the next line of code is executed.

However, in the last two lines of code, the output parameter is changed from t1 to t1.Result (from t2 to t2.Result). Since Result is of type Task<int>, these two lines of code need to wait for the completion of DownloadStringTaskAsync to return Its value can be output. If the method has not been executed, it blocks and waits for the expiration value to arrive.

The above example uses asynchronous calls, but does not open up new threads. It is because the main thread of the program calls DownloadStringTaskAsync asynchronously to tell the system that it wants to obtain resources, and then continues to do its own thing. If in the middle process, after the background system requests the network to get the result, it will tell the main thread and return the result to it, then it will stop the work at hand and continue to process this matter, and then continue to execute the work at hand after processing.

Please add a picture description

From the output results of the above two examples, it can be seen that if there is a code block that needs to wait in the method, it will take longer when the method is a synchronous method than when it is an asynchronous method.
(In the example of not using asynchronous, the entire process of execution of the method takes 3,323ms; and after using asynchronous, it takes 925ms. The main reason for the gap is that when the synchronous method waits for resources, it will stop. Work until a result is returned before continuing to work. While the asynchronous method waits for resources, it continues to process other things.)

2. Structure of async/await feature

Synchronous method: If a program calls a method and waits for the method to perform all processing before continuing.
Asynchronous method: returns to the calling method before completing all of its methods.
characteristic:

  • Call method: This method calls the asynchronous method, and then continues execution (maybe on the same thread or a different thread) while the asynchronous method performs its task.
  • Asynchronous method: The method performs its work asynchronously and then immediately returns to the calling method.
  • awaite expression: Used inside an asynchronous method to indicate the tasks that need to be executed asynchronously. An asynchronous method can contain any number of await expressions, but the compiler will issue a warning if none are included. (Presumably a warning: if you don't use an await expression, it's considered synchronous.)

3. The overall structure of async/await features

//调用方法
static void Main()
{
Task<int> value DoAsyncStuff.CalculateSumAsync(5,6);
}

//异步方法
staic class DoAsyncStuff
{
public static async Task<int> CalculateSumAsync(int i1,int i2)
{
int sum = await TaskEx.Run(() => GetSum(i1,i2));
return sum;
}
}

Guess you like

Origin blog.csdn.net/chen1083376511/article/details/131267868