Simple understanding of threads and coroutines (C#)

1. Why threads and coroutines are needed:
(1) Make the tasks in the program execute concurrently, let the program process multiple tasks at the same time, improve the operating efficiency and response speed of the program
(2) Threads and coroutines can share the same process resources to avoid waste of resources between multiple processes
(3) The concurrency of the program can be dynamically adjusted to improve the scalability of the program to adapt to different load situations
(4) Split the program into multiple tasks to make the program 2. The difference between
threads and coroutines: Threads are scheduled by the operating system, while coroutines are controlled by the program itself.
Application of threads:
(1) Some time-consuming operations can be performed in sub-threads to avoid blocking the main thread and improve user experience.
(2) Threads can be used to handle some tasks with high real-time requirements, such as network communication, I/O operations, etc.
Application of coroutines:
(1) It can be used to realize the animation effects in the game, such as the movement and attack of characters.

(2) It can be used to implement asynchronous request processing in the server, such as asynchronously reading the database, asynchronously processing requests, etc.

 1.
Some attributes of thread 1..Thread class

using System;
using System.Threading;

namespace ThreadTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            ThreadStart childRef = new ThreadStart(ChildMethod);
            Thread th=new Thread(ChildMethod);
            th.Start();
            //Thread类的一些属性,属性表示的意思,可参考:https://www.runoob.com/csharp/csharp-multithreading.html
            Console.WriteLine(Thread.CurrentContext);
            Console.WriteLine(Thread.CurrentPrincipal);
            Console.WriteLine(Thread.CurrentThread);//获取当前正在运行的线程
            Console.WriteLine(th.CurrentCulture);
            Console.WriteLine(th.CurrentUICulture);
            Console.WriteLine(th.ExecutionContext);
            Console.WriteLine(th.IsAlive);//获取表示当前线程执行状态的一个值
            Console.WriteLine(th.IsBackground);是否为后台线程
            Console.WriteLine(th.IsThreadPoolThread);
            Console.WriteLine(th.ManagedThreadId);
            Console.WriteLine(th.Name);//获取或设置线程的名称
            Console.WriteLine(th.Priority);//获取或设置线程的调度优先级
            Console.WriteLine(th.ThreadState);
        }
        static void ChildMethod()
        {
            Thread.Sleep(2000);//线程休眠,让线程暂停一段时间
            Console.WriteLine("Child");
        }
    }
}

 2. Create a thread

using System;
using System.Threading;

namespace ThreadTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //第一种方式,通过ThreadStart线程入口创建,它是一个无参无返回值的委托
            Thread th1 = new Thread(new ThreadStart(ThreadTest));
            //第二种方式,直接传递方法,这方式本质是与第一种方式是一样的,直接传递方法后,Thread内部会自动转成ThreadStart,因此一般情况不用担心因为重载问题而使它报错,因为TreadStart是无参无返回值的,它会自动匹配对应的方法类型,如果没有找到对应的类型就会提示报错
            Thread th2 = new Thread(ThreadTest1);
            //第三种方式,通过ParameterizedThreadStart创建,它是一个有参无返回值的委托,且只有一个参数
            Thread th3=new Thread(new ParameterizedThreadStart(ThreadTest2));
            //第四种方式,使用Lambda表达式创建线程,可以自己定义参数的传递
            //至于为什么可以这样写,可以参考:https://www.cnblogs.com/eve612/p/14342087.html
            Thread th4 = new Thread(() => ThreadTest3("Lambda","很好用"));
            th1.Start();//开启线程
            th2.Start();
            th3.Start();
            th4.Start();
        }

        static void ThreadTest()
        {
            Console.WriteLine("Thread");
        }
        static void ThreadTest1()
        {
            Console.WriteLine("Thread1");
        }
        static void ThreadTest2(object obj)
        {
            Console.WriteLine("ParameterizedThreadStart");
        }
        static void ThreadTest3(string str,string info)
        {
            Console.WriteLine(str+info);
        }
    }
}

More content: https://www.cnblogs.com/eve612/p/14342087.html

3. Terminate the thread

using System;
using System.Threading;
using System.Threading.Tasks;

namespace ThreadTest
{
    internal class Program
    {

        static void Main(string[] args)
        {
            Console.WriteLine("主线程开始");
            Thread th = new Thread(new ThreadStart(Test));
            th.Start();
            Thread.Sleep(1000);//线程休眠,阻止当前线程1s
            //终止进程,会引发ThreadAbortException异常
            //th.Abort();
            th.Abort("我们要终止子线程");//重载方法,终止进程的同时传递终止的异常信息
            Console.WriteLine("主线程结束");
        }
        static void Test()
        {
            try
            {
                Console.WriteLine("子线程开始");
                for(int i=0;i<10;i++)
                {
                    Thread.Sleep(400);
                    Console.WriteLine(i);
                }
            }
            catch(ThreadAbortException e)
            {
                //Console.WriteLine(e.Message);
                Console.WriteLine(e.ExceptionState);//打印终止的异常信息
            }
            finally
            {
                Console.WriteLine("捕获不到异常");
            }
            Console.WriteLine("子线程结束");
        }
    }
}

4. Thread priority: Each thread has a default priority. A thread with a higher priority has a better chance of being scheduled first than a thread with a lower priority, but it is not absolute. (Priority values ​​from high to low: Highest, AboveNormal, Normal, BelowNormal, Lowest)

using System;
using System.Threading;

namespace ThreadTest
{
    internal class Program
    {

        static void Main(string[] args)
        {
            Thread th1 = new Thread(new ThreadStart(Test));
            Thread th2 = new Thread(new ThreadStart(Test2));
            th2.Priority=ThreadPriority.Highest;
            th1.Priority=ThreadPriority.Lowest;
            th1.Start();
            th2.Start();
        }
        static void Test()
        {
            for(int i = 0; i < 10; i++)
            {
                Console.WriteLine("子线程1");
            }
        }
        static void Test2()
        {
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("子线程2");
            }
        }
    }
}

5. Lock: Realize thread synchronization
Thread synchronization: A thread must wait for the previous thread to finish executing before starting to execute the current thread Thread
asynchronous: Threads go their own way, and start executing without relative waiting

using System;
using System.Threading;

namespace ThreadTest
{
    internal class Program
    {
        static LockTest kt=new LockTest();
        static void Main(string[] args)
        {
            Thread th1 = new Thread(new ThreadStart(kt.Test));
            Thread th2 = new Thread(new ThreadStart(kt.Test2));
            th1.Start();
            th2.Start();
        }
    }
    public class LockTest
    {
        public void Test()
        {
            lock (this)//给线程加锁,确保代码块能完整运行,而不会被其它线程打断,this不能在静态方法中使用
            {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("子线程1");
                }
            }
        }
        public void Test2()
        {
            lock(this)
            {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("子线程2");
                }
            }
        }
    }
}

reference:

https://www.cnblogs.com/zhan520g/p/11388591.html
https://blog.csdn.net/u012395622/article/details/46581359
https://www.runoob.com/csharp/csharp-multithreading.html
https://blog.csdn.net/m0_67296957/article/details/126910726
https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.thread?view=net-7.0

2. Coroutine : While the main program is running, another piece of logic processing is started to assist the execution of the main program.
The use of coroutines in Unity is mostly to delay calling a certain function method or module Operations that control the time axis such as parallel operations that do not require high parallelism or delayed execution (for delayed calls, Unity also has an Invoke function, but the function to be called by Invoke must be a method in the current class)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class IEnumeratorTest : MonoBehaviour
{
    Coroutine mCoroutine=null;//定义协程
    WaitForSeconds waitS = new WaitForSeconds(5.0f);
    // Start is called before the first frame update
    void Start()
    {
        //调用和暂停协程
        //方式一
        //StartCoroutine(Test());
        //StopCoroutine(Test());这种方式无法停止协程
        //方式二
        //StartCoroutine("Test");
        //StopCoroutine("Test");//可以暂停协程
        //方式三
        mCoroutine = StartCoroutine(Test());
        //StopCoroutine(mCoroutine);//可以暂停协程
    }
    //协程函数
    IEnumerator Test()
    {
        Debug.Log("开始");
        //yield的多用方法:
        //yield return new WaitForEndOfFrame();//每帧结束后再执行
        //yield return new WaitForFixedUpdate();//等待FixEdUpdate结束后再执行
        //yield return new WaitForSeconds(5.0f);//等待5s后执行
        //用全局中断指令来控制
        //yield return waitS;//等待5s后执行
        yield return StartCoroutine(Test2());//在协程中开启协程,协程一旦开启,就会立即执行
        Show();
        Debug.Log("等待了5s");
    } 
    IEnumerator Test2()
    {
        //yield return new WaitForSeconds(2.0f);//程序等待N秒后从当前位置继续执行
        //yield return null;//程序在下一帧中从当前位置继续执行
        //yield return 0;//程序在下一帧中从当前位置继续执行
        yield break;//直接终止协程
        Debug.Log("第二个协程");
    }
    void Show()
    {
        Debug.Log("Show");
    }
}

Reference: Unity C# coroutine: (start a coroutine, stop a coroutine, optimize coroutine, usage of yield in coroutine)_c# stop coroutine_Iamzls' Blog-CSDN Blog

Conclusion: The tree that embraces is born at the end of the hair; the nine-story platform starts from the pile of soil; the journey of a thousand miles begins with a single step.

Guess you like

Origin blog.csdn.net/falsedewuxin/article/details/130181837