线程、task以及async/await

Thread属性:

CurrentContext 获取线程正在其中执行的当前上下文。(获取ContextID)
CurrentCulture 获取或设置当前线程的区域性。
CurrentPrinciple 获取或设置线程的当前负责人(对基于角色的安全性而言)。
CurrentThread 获取当前正在运行的线程。
CurrentUICulture 获取或设置资源管理器使用的当前区域性以便在运行时查找区域性特定的资源。
ExecutionContext 获取一个 ExecutionContext 对象,该对象包含有关当前线程的各种上下文的信息。
IsAlive 获取一个值,该值指示当前线程的执行状态。
IsBackground 获取或设置一个值,该值指示某个线程是否为后台线程。
IsThreadPoolThread 获取一个值,该值指示线程是否属于托管线程池。
ManagedThreadId 获取当前托管线程的唯一标识符。
Name 获取或设置线程的名称。
Priority 获取或设置一个值,该值指示线程的调度优先级。
ThreadState 获取一个值,该值包含当前线程的状态。

 线程优先级别:

Highest > AboveNormal > Normal(默认) > BelowNormal > Lowest

Thread方法:

public void Abort()  在调用此方法的线程上引发 ThreadAbortException,以开始终止此线程的过程。调用此方法通常会终止线程。

public static LocalDataStoreSlot AllocateDataSlot() 在所有的线程上分配未命名的数据槽。为了获得更好的性能,请改用以 ThreadStaticAttribute 属性标记的字段。

public static LocalDataStoreSlot AllocateNamedDataSlot( string name) 在所有线程上分配已命名的数据槽。为了获得更好的性能, 请改用以 ThreadStaticAttribute 属性标记的字段。

public static void BeginCriticalRegion()通知主机执行将要进入一个代码区域,在该代码区域内线程中止或未经处理的异常的影响可能会危害应用程序域中的其他任务。

  

案例:

using System;
using System.Threading;

namespace ConsoleApplication2
{
    class Program
    {
        public static void test_one()
        {
            Console.WriteLine("这好似一个子进程...");
            Console.Write("子进程正在准备休眠5秒");
            for (int i = 0; i < 5; i++)
            {
                Thread.Sleep(1000);  // 休眠1秒,单位是毫秒
                Console.Write("");
            }
            Console.WriteLine();
        }
        static unsafe void Main(string[] args)
        {
            /*
            Thread th = Thread.CurrentThread;  // 获取当前运行的线程
            th.Name = "mainThread";  // 修改线程名字
            Console.WriteLine(th.Name);
            */
            //
            ThreadStart ts = new ThreadStart(test_one);  // 创建将要执行的子进程
            Console.WriteLine("主线程已经创建子进程...");
            Thread cth = new Thread(ts);  // 子进程初始化
            cth.Start();  // 进程执行
        }
    }
}
/*
 * 用户: NAMEJR
 * 日期: 2019/8/4
 * 时间: 10:49
 */
using System;
using System.Threading;

namespace 线程
{
    class Program
    {
        public static void Main(string[] args)
        {
            Thread thread = new Thread(ConsoleText);  // 实例化一个线程
            thread.IsBackground=true;  // true表示将当前线程设置为前台进行,执行完主程序会退出。默认为false,执行完主窗体程序不会退出
            thread.Priority = ThreadPriority.Normal;  // 建议系统设置优先级
            thread.Start();  // 线程开始
            Console.WriteLine("主线程ID:"+thread.ManagedThreadId);
            Console.WriteLine("子线程ID:"+Thread.CurrentThread.ManagedThreadId);
            //thread.Abort();  // 终止线程(一般不用,不得已才用)
            thread.Join();  // 等待线程执行完成,参数为超时时间
            Console.ReadKey();
        }
        
        public static void ConsoleText()
        {
            while(true)
            {
                Console.WriteLine(DateTime.Now);
                Thread.Sleep(1000);  // 毫秒为单位
            }
        }
    }
}
/*
 * 用户: NAMEJR
 * 日期: 2019/8/4
 * 时间: 11:54
 */
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

namespace 窗体线程
{
    /// <summary>
    /// Description of MainForm.
    /// </summary>
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }
        
        void Btn_ThreadClick(object sender, EventArgs e)
        {
            // 解决线程间的控件问题
            Thread thread = new Thread(()=>{
                                           // InvokeRequired:用来判断控件是否由当前线程创建,不是返回true
                                           if(TB_Msg.InvokeRequired){
                                               // TB_Msg.Invoke:Invoke表示找到TB_Msg创建的线程
                                               TB_Msg.Invoke(new Action<string>(s=>{this.TB_Msg.Text=s;}),"当前线程输入,输入时间:"+DateTime.Now);
                                           }else{
                                               // 如果不是当前线程创建,那就表示是主窗体线程
                                               this.TB_Msg.Text="窗体线程输入,输入时间:"+DateTime.Now;
                                           }
                                       });
            thread.IsBackground=true;
            thread.Start();
        }
    }
}
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.IO;
using System.Windows.Forms;
using System.Threading;
using System.Timers;

namespace 控制台临时代码
{
    class Program
    {
        public static void Main(string[] args)
        {
            // 带参线程
            Thread thread1 = new Thread(test);
            thread1.IsBackground = true;
            thread1.Start("123");
            thread1.Join();
        }
        // 所带参数必须为object
        public static void test(object l_objStr)
        {
            for(int i=0;i<999999;i++)
            {
                Console.WriteLine(l_objStr.ToString());
                Thread.Sleep(1);
            }
        }
    }
}

ThreadPool线程池:

公共语言运行库CRL中的线程池分为两种:工作者模式(workerThreads)和I/O模式(completionThreads)。工作者模式主要用来做密集的任务计算;I/O主要用来与外部系统进行交互。

使用线程池的好处:减少系统重复创建线程的响应和分配资源时间,以及资源分配的开销。缺点:不能再对每个线程进行监控。(其实每个语言都差不多)

Add by 2019-9-23

线程池最多管理线程数量=“处理器数 * 250”。也就是说,如果您的机器为2个2核CPU,那么CLR线程池的容量默认上限便是1000(这句话来源自:https://www.cnblogs.com/qixuejia/p/7802092.html,作者:Cat Qi,如果想仔细了解线程及线程池可以去看看这个文章)

End Add

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        // 获取系统信息
        private static void GetSystemInfo(object a_obj)
        {
            IDictionary l_idInfos = System.Environment.GetEnvironmentVariables();
            foreach(DictionaryEntry l_idInfo in l_idInfos)
            {
                Console.WriteLine("系统信息:key={0}, value={1}", l_idInfo.Key, l_idInfo.Value);
            }
            Console.WriteLine("=================");
        }
        static void Main(string[] args)
        {
            ThreadPool.SetMaxThreads(10, 10);  // 设置最大的线程数,第一个参数为工作者模式,第二个参数为I/O模式
            ThreadPool.SetMinThreads(5, 5);  // 设置最小线程数
            ThreadPool.GetAvailableThreads(out int a_GetWorkerThreadsNum, out int a_GetCompletionThreadsNum);   // 返回剩余空闲线程数
            ThreadPool.QueueUserWorkItem(new WaitCallback(GetSystemInfo));  // 将方法排入队列
        }
    }
}

 这里的信息不够详细,如果想仔细看,请转往这个大佬的博客:https://www.cnblogs.com/scmail81/p/9503266.html

 Task:

 创建一个简单地task

class Program
    {
        static void Main(string[] args)
        {
            // 创建task
            Task l_task = new Task(() =>
            {
                Console.WriteLine("正在task内部执行....");
                Thread.Sleep(100);
            });
            l_task.Start();  // 启动
            l_task.ContinueWith((l_parameter) =>
            {
                // task不同于线程池,可以获取上一个线程的状态
                Console.WriteLine("上一个任务的状态:");
                Console.WriteLine("IsCanceled={0}	IsCompleted={1}	IsFaulted={2}", l_parameter.IsCanceled, l_parameter.IsCompleted, l_parameter.IsFaulted);  // IsCanceled(被取消而完成)、IsCompleted(是否已经完成)、IsFaulted(未处理异常而完成)获取执行情况
            });
            Console.ReadKey();
        }
    }

关于WaitAll/WaitAny和Task.Factory.StartNew的使用

class Program
    {
        static void Main(string[] args)
        {
            Task l_task1 = new Task(() => Func1("Task1"));
            Task l_task2 = new Task(() => Func1("Task2"));
            l_task2.Start();
            l_task1.Start();
            Task.WaitAll(l_task1, l_task2);  // 等待前两个(所有)任务完成。Task.WaitAny()等待任何一个任务完成
            Task.Run(() => Func1("Task3"));
            Task.Factory.StartNew(() => Func1("Task4"));  // 创建并启动任务
            Task.Factory.StartNew(() => Func1("Task5"), TaskCreationOptions.LongRunning);
            
            Console.ReadKey();
        }

        public static void Func1(string name1)
        {
            Console.WriteLine("{0}任务正在执行...", name1);
        }
    }
class Program
    {
        static void Main(string[] args)
        {
            Task<int> l_task1 = Func1();
            //l_task1.RunSynchronously();  // 将当前的task(l_task1)其变成同步运行
            l_task1.Start();
            l_task1.Wait();  // 等待l_task1完成执行
            int l_intResult = l_task1.Result;  // 获取返回值
            Console.WriteLine(l_intResult.ToString());
            Console.ReadKey();
        }

        public static Task<int> Func1()
        {
            return new Task<int>(()=> { return 1; });
        }
    }
class Program
    {
        // await还可以适用于组合任务中
        static void Main(string[] args)
        {
            Task<int> l_task1 = new Task<int>(()=> {
                Console.WriteLine("1");
                return 1;
            });
            l_task1.Start();
            Task l_task2 = l_task1.ContinueWith(parameter => {
                Console.WriteLine("2");
                Console.WriteLine(parameter.Result.ToString());
            });
            l_task1.Wait();
            l_task2.Wait();
            Console.ReadKey();
        }
    }

带参数:

class Program
    {
        static void Main(string[] args)
        {
            Task<int> l_task1 = Func1();
            l_task1.Start();
            int l_intResult = l_task1.Result;  // 获取返回值
            Console.WriteLine(l_intResult.ToString());
            Console.ReadKey();
        }

        public static Task<int> Func1()
        {
            return new Task<int>(()=> { return 1; });
        }
    }

async/await在Task中的使用

using System.Threading.Tasks;
...
class
Program { static void Main(string[] args) { Console.WriteLine("这是最前面执行的方法..."); Func1(); Console.WriteLine("这是Func1之后的方法"); Console.ReadKey(); } // 异步 public async static void Func1() { await Task.Delay(1000); // 等待,缺少该方法将会以同步运行的方式,在这里以毫秒为单位 Console.WriteLine("这本该是第二个输出..."); } }
class Program
    {
        static void Main(string[] args)
        {
            Task<int> l_task1 = ReverInt(98541);
            Console.WriteLine("最先输出...");  // 立马输出
            l_task1.Wait();  // 等待l_task1执行完成
            Console.WriteLine("最后输出...");  // 1秒后输出
            Console.WriteLine("结果为:{0}", l_task1.Result);  // 输出结果
            Console.ReadKey();
        }

        public async static Task<int> ReverInt(int a_intNum)
        {
            int l_intRevNum = 0;
            int l_intTempNum = a_intNum;
            while(l_intTempNum!=0)
            {
                l_intRevNum = l_intRevNum * 10 + l_intTempNum % 10;
                l_intTempNum /= 10;
            }
            await Task.Delay(1000);
            return l_intRevNum;
        }
    }

AddBy  2021-01-10

Task、task任务并行(task并行库)笔记

内容来源:https://www.cnblogs.com/yaopengfei/p/8183530.html(task使用,逻辑清晰)

https://www.cnblogs.com/InCerry/p/9450493.html(内容讲的详细,并行以及模式讲解)

EndBy 2021-01-10

原文地址:https://www.cnblogs.com/namejr/p/10486631.html