A first look at the function of logging net (Async)

1. Write in front

I've been studying the code of our products recently, In some functions Asynchrony has been used in (for example, warehousing), but it has not been studied in detail for so long. Many popular explanations of relevant contents on the Internet are based on life examples such as making tea and washing clothes. Personally, I think it has no problem in understanding the role of asynchrony, but I still can't use it well when I really encounter problems. So I also wrote some instructions when learning relevant contents The main function of the example code is to simulate a time-consuming operation and log recording (because our product also has the function of response). It is implemented with two ideas: await/async syntax sugar of. net4.5 or above and IAsyncResult of. net.

2. Functional design

The following form is designed. The two buttons simulate two time-consuming operations through await/async and IAsyncResult respectively, and simulate logging in the text box at the bottom.

3. await/async implementation

The binding code of the form above the form is as follows:

        private async void button1_ClickAsync(object sender, EventArgs e)
        {
            Class1 class1 = new Class1();
            class1.WriteLogHandle += WriteSystemLogAction;
            int a = await class1.MethodA();
            Notice("Final result:" + a);
        }

Binding logging method:

        private void WriteSystemLogAction(string logStr)
        {
            //The second method is to solve the "invalid inter thread operation" error
            Action<string> action = new Action<string>(WriteText);
            this.Invoke(action, logStr);
        }
        private void WriteText(string s)
        {
            this.richTextBox1.AppendText(String.Format("\n{0}\t{1}", System.DateTime.Now.ToLongTimeString(), s));
            this.richTextBox1.SelectionStart = richTextBox1.Text.Length;
            richTextBox1.Focus();
        }

At first, there was no delegation. This error was encountered. Originally, windows forms controls are not thread safe. If several threads operate on the state of a control, the state of the control may be inconsistent, resulting in contention or deadlock. Therefore, the delegation mechanism should be used to realize thread safety. Of course, you can also set control when initializing the control CheckForIllegalCrossThreadCalls = false;, But Microsoft does not recommend this approach.

There is a prompt method in the method of the main form:

        private void Notice(string msg)
        {
            MessageBox.Show(msg);
        }

In Class1 In CS, a log writing delegate is defined,

        //Logging delegation
        public Action<string> WriteLogHandle;

Define a method to instantiate a delegate:

        //Instantiate delegate
        private void WriteLog(string log)
        {
            if (WriteLogHandle != null)
            {
                WriteLogHandle(log);
            }
        }

Finally, simulate a time-consuming operation and record the log. The simulated operation is to calculate the cumulative value, sleep 1 seconds for each calculation, record the number added each time, and finally return the calculation result:

        //await/async sample method
        public async Task<int> MethodA()
        {
            int result=await Task.Run(()=>{
                int temp = 0;
                for (int i = 0; i < 5; i++)
                {
                    Thread.Sleep(1000);
                    WriteLog("Calculating"+temp+"+" + i.ToString() + ";Current thread" + Thread.CurrentThread.ManagedThreadId.ToString());
                    temp += i;
                }
                return temp;
            });
            return result;
        }

The final running results are as follows:

Probably explain it. It may not be explained in depth enough. I hope you can point out the deficiencies. In the MethodA() method, use Task to create a new thread, which is used to calculate the cumulative value. The await keyword is in net official document:

The await operator is applied to the task of an asynchronous method and suspends the execution of the method until the task is completed. Tasks represent ongoing work.
The await expression does not block the thread on which it executes. Instead, it causes the compiler to register the rest of the asynchronous method for the waiting task to continue. The control then returns to the caller of the asynchronous method. When the task completes, its continuation task is called, and the execution of the asynchronous method resumes where it will stop.

The description of async is:

Asynchronous methods provide an easy way to do work that may take a long time without blocking the caller's thread. Callers of asynchronous methods can continue to work without waiting for the asynchronous method to complete.

My understanding is that the UI thread calls the async modified asynchronous method MethodA(). The UI thread will not block and can perform other operations (such as dragging a form). You can try to modify this method as follows. You will find that the form pops up directly without waiting for the return of the calculation result.

        private async void button1_ClickAsync(object sender, EventArgs e)
        {
            Class1 class1 = new Class1();
            class1.WriteLogHandle += WriteSystemLogAction;
             class1.MethodA();
            Notice("Final result:");
        }

When the MethodA() method opens a new thread with a Task, the result variable waits for the return result of the thread. After the result is returned, the MethodA() method returns the result value to the UI thread, and the UI thread pops up a prompt box for the result.

4,IAsyncResult

IAsyncResult is mainly implemented by delegation. First, write a method MethodB() to simulate time-consuming operations and record logs. The WriteLog method of logging is WriteLog in method 3:

        //IAsyncResult method
        public int MethodB()
        {
            int temp = 0;
            for (int i = 0; i < 5; i++)
            {
                Thread.Sleep(1000);
                WriteLog("Calculating" + temp + "+" + i.ToString() + ";Current thread" + Thread.CurrentThread.ManagedThreadId.ToString());
                temp += i;
            }
            return temp;
        }

First, define the delegate in Class1, instantiate the delegate in the constructor, and bind the Method method.

        public delegate int AsyncTestDelegate();
        public AsyncTestDelegate asyncTestDelegate;
        public Class1()
        {
            if (asyncTestDelegate == null)
            {
                asyncTestDelegate = MethodB;
            }
        }

Next, write the control method of the form, BeginInvoke() method:

        private void button2_Click(object sender, EventArgs e)
        {
            Class1 class1 = new Class1();
            class1.WriteLogHandle += WriteSystemLogAction;
            IAsyncResult asyncResult = class1.asyncTestDelegate.BeginInvoke(null, null);
            while (!asyncResult.IsCompleted)
            	Application.DoEvents();
            Notice(class1.asyncTestDelegate.EndInvoke(asyncResult).ToString());
        }

The while loop is mainly used to avoid jamming when waiting for the return result.
The final result is the same as that in 3.

5. Finally

I've just touched the content of asynchronous multithreading. Some things are really not deep enough. I hope all experts can give me more advice. Relevant codes have been uploaded:
Code cloud Download: https://gitee.com/ranhongwu/dotnet-async-test

Keywords: C# Programming Multithreading .NET

Added by dcmbrown on Thu, 30 Dec 2021 21:42:53 +0200