我的编程空间,编程开发者的网络收藏夹
学习永远不晚

c#多线程—基础概念到“双色球”项目实现(附知识点目录、代码、视频)

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

c#多线程—基础概念到“双色球”项目实现(附知识点目录、代码、视频)

总结:视频中对于多线程讲的非常透彻,从线程基础概念—>.net不同版本出现的线程方法—>多线程常出现问题—>双色球项目实践,每个知识点都有代码实操,受益匪浅。附上学习笔记和实操代码。
视频

目录

一、线程、进程概念及优缺点

线程:程序执行的最小单位,任何操作都是由线程完成的,使用同步时,资源一直被此线程占用,所以其他界面干不了,会出现卡界面的现象。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
1启动不可控制、2结束不可控
在这里插入图片描述
主线程代码
一个耗时(i++)、耗资源(thread.sleep)的方法
在这里插入图片描述

二、四种异步等待方式

1.异步控制等待-callback回调

action执行完将asyncResult、"nimen"当成参数传给callback
在这里插入图片描述

2.异步控制等待-asyncResult.IsCompleted

在这里插入图片描述

3.异步控制等待WaitOne()-信号量

在这里插入图片描述

4.异步控制等待endinvoke-拿到异步函数的返回值

在这里插入图片描述
在这里插入图片描述

5.视频第1节课代码

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Windows.Forms;namespace multithread{    public partial class Form1 : Form    {        public Form1()        {            InitializeComponent();        }        private void button1_Click(object sender, EventArgs e)        {            Console.WriteLine($"[------------主线程start: 线程号:({Thread.CurrentThread.ManagedThreadId.ToString("00")})---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}-----]");                                                                                                Console.WriteLine($"[------------主线程end: 线程号:({Thread.CurrentThread.ManagedThreadId.ToString("00")})---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}-----]");        }        private void dosomething(string name)        {            Console.WriteLine($"[****Dosomething {name} start: 线程号:({Thread.CurrentThread.ManagedThreadId.ToString("00")})---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}*******]");            long result = 0;            for(int i =0; i < 10000000; i++)            {                result += i;            }            Thread.Sleep(2000);            Console.WriteLine($"[****Dosomething {name} end: 线程号:({Thread.CurrentThread.ManagedThreadId.ToString("00")})---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}{result}*******]");        }    }}

三、.net1.0基础版的thread对象

1.线程启动

 {                //Action action = this.dosomething;                //IAsyncResult asyncResult = action.BeginInvoke("cc", null, null);                //Action action1 =()=> this.dosomething("CC");                //1.线程启动 thread.Start();                ThreadStart threadStart = () => this.dosomething("cc");                Thread thread = new Thread(threadStart);                thread.Start();                //2.线等待程thread.Join();                thread.Join(500);//卡主线程                Console.WriteLine($"等待500ms");                thread.Join();                while (thread.ThreadState != ThreadState.Stopped)                {                    Thread.Sleep(100);//cpu时间片交出去干其他的事,但是内存还是占用                }

在这里插入图片描述

2.thread.join()\thread.sleep()\thread.IsBackfround

thread.join(500),是其他人线程等他500ms,此时有两个线程在工程, 一个在等待500ms,一个是自己在运行
thread.sleep(500),是自己线程自己将cpu时间片交出去干其他的事,但是内存还是占用,休眠500ms
前台线程,当软件闪退时,会吐出日志
在这里插入图片描述

四、net 2.0 threadpool

在这里插入图片描述

1.线程启动、设置线程池最大线程数

在这里插入图片描述
在这里插入图片描述

2.manualResetEvent.WaitOne()异步控制等待

            {                ManualResetEvent manualResetEvent = new ManualResetEvent(false);                ThreadPool.QueueUserWorkItem(t =>                 {                    this.dosomething("cc");                    manualResetEvent.Set();                });//接收一个没有返回值的委托                manualResetEvent.WaitOne();                Console.WriteLine($"等待ThreadPool.QueueUserWorkItem执行完再执行");            }

在这里插入图片描述
waitone()风险,无线程可用会卡住
在这里插入图片描述

3.手写异步回调函数

在这里插入图片描述

4.带返回值的委托异步调用(法语结构待学习)

在这里插入图片描述

五、.net3.0 task

1.task线程启动

在这里插入图片描述

2.waitall、waitany都会卡主线程卡界面

在这里插入图片描述
在这里插入图片描述
waitall、waitany应用场景
在这里插入图片描述

3.task.whenall.continuewith()

首先task.whenall不卡主界面,快快的结束了btn_task_click是主线程任务
其次continuewith() ,当tasklist中线程执行后并满足条件时(all\any),直接顺序执行下面的委托,类似回调如“得意的笑”
在这里插入图片描述
在这里插入图片描述

4.taskfactory.continuewith()

在这里插入图片描述
在这里插入图片描述

5.设计最多只有11个线程在工作

在这里插入图片描述

6.taskfactory检测到哪个线程结束后,返回线程标识

在这里插入图片描述
在这里插入图片描述

7.task多次嵌套实现不卡主线程

在这里插入图片描述
在这里插入图片描述

8.两个waitall按顺序执行

如果有两个waitall需要执行但他们在不同线程中,但是又要保证这两次waitall的顺序,解决办法,将第一个waitall加到tasklist中,然后让第二个task的waitall来判断
在这里插入图片描述

9.thread.sleep()卡线程 task.delay()不卡线程

在这里插入图片描述
在这里插入图片描述

10.task线程完成标识

在这里插入图片描述

六、.net4.5 parallel

1.parallel启动多线程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.parallel线程停止

在这里插入图片描述

七、threadcore

1.异常处理

主线程出现异常没人管理会导致程序崩溃
在这里插入图片描述
在这里插入图片描述

  try {                TaskFactory taskFactory = new TaskFactory();                List < Task > tasklist = new List<Task>();                //异常处理                    for(int i =0;i<20; i++)                    {                        string name = string.Format($"btn_click_{i}");                        Action<object> act = t =>                        {try{    Thread.Sleep(2000);    if (t.ToString().Equals("btn_click_11"))    {        throw new Exception(string.Format($"{t}执行失败"));    }    if (t.ToString().Equals("btn_click_12"))    {        throw new Exception(string.Format($"{t}执行失败"));    }    Console.WriteLine("{0}执行成功", t);}catch (Exception ex){    Console.WriteLine(ex.Message);}                        };                        tasklist.Add(taskFactory.StartNew(act, name));                    };                   Task.WaitAll(tasklist.ToArray());            }             catch (AggregateException aex)            {                foreach(var item in aex.InnerExceptions)                {                    Console.WriteLine(item.Message);                }            }            catch(Exception ex)            {                Console.WriteLine(ex.Message);            }            

2.线程取消

在这里插入图片描述
tasklist.Add(taskFactory.StartNew(act, name))时,
在这里插入图片描述
tasklist.Add(taskFactory.StartNew(act, name,cts.Token))时,
在这里插入图片描述

 try {                TaskFactory taskFactory = new TaskFactory();                List < Task > tasklist = new List<Task>();                CancellationTokenSource cts = new CancellationTokenSource();                    for(int i =0;i<40; i++)                    {                        string name = string.Format($"btn_click_{i}");                        Action<object> act = t =>                        {try{    Thread.Sleep(2000);    if (t.ToString().Equals("btn_click_11"))    {        throw new Exception(string.Format($"{t}执行失败"));    }    if (t.ToString().Equals("btn_click_12"))    {        throw new Exception(string.Format($"{t}执行失败"));    }        if (cts.IsCancellationRequested)    {        Console.WriteLine("{0}放弃执行", t);        return;    }    else    {        Console.WriteLine("{0}执行成功", t);    }}catch (Exception ex){    cts.Cancel();    Console.WriteLine(ex.Message);}                        };                        tasklist.Add(taskFactory.StartNew(act, name,cts.Token));                    }                Task.WaitAll(tasklist.ToArray());            }             catch (AggregateException aex)            {                foreach(var item in aex.InnerExceptions)                {                    Console.WriteLine(item.Message);                }            }            catch(Exception ex)            {                Console.WriteLine(ex.Message);            }

3.多线程临时变量

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.线程安全lock(lock锁的是引用)

在这里插入图片描述

4.1线程安全问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.2线程共有变量存在线程安全问题

在这里插入图片描述

4.3lock锁原理

只有一个线程可以进去,没有并发 ,解决问题但牺牲性能
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
建议使用微软定义的锁
在这里插入图片描述

private static readonly object btn_click_lock = new object();//引用型变量        private int TotalCount = 0;        private List<int> IntList = new List<int>();        private void button1_Click(object sender, EventArgs e)        {          Console.WriteLine($"[------------主线程start: 线程号:({Thread.CurrentThread.ManagedThreadId.ToString("00")})---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}-----]");          TaskFactory taskFactory = new TaskFactory();        //private static readonly object btn_click_lock = new object();        List<Task> tasklist = new List<Task>();            for (int i = 0; i< 10000; i++)            {                int newI = i;                                //多线程                tasklist.Add(taskFactory.StartNew(() =>                 {                   // int m = 3 + 2;                   lock (btn_click_lock)                     {                     this.TotalCount += 1;                    this.IntList.Add(newI);                    }                }));            }            Task.WaitAll(tasklist.ToArray());            Console.WriteLine(this.TotalCount);            Console.WriteLine(this.IntList.Count());         Console.WriteLine($"[------------主线程end: 线程号:({Thread.CurrentThread.ManagedThreadId.ToString("00")})---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}-----]");        }

八、.net.0 await/async

在这里插入图片描述

1.await原理

在这里插入图片描述
在这里插入图片描述

await后的代码相当于回调,只不过不是自己写的,是编译器状态机自带的。
回调方法continuewith是子线程完成的,但await不仅仅是回调(可子线程可主线程,计算机分配),所以他们又有所不同

在这里插入图片描述

1.1小代码测试原理

在这里插入图片描述

2.带与不带返回值的async方法

2.1只有asynic

在这里插入图片描述

2.2asynic\await成对出现

await 后面是要跟带有返回值的方法
在定义方法时,有了async和await套装后,尽管方法没有return,但此方法也可看成是带返回值的

不使用返回值
在这里插入图片描述
使用返回值
在这里插入图片描述

2.3t.Wait()与await t区别

在这里插入图片描述

2.4await反编译-相当于状态机

在这里插入图片描述
在这里插入图片描述

3.此知识点代码

 private void button1_Click(object sender, EventArgs e)        {            testshow();        }        public static void testshow()        {            test();        }        private async static Task test()        {            Console.WriteLine($"当前主线程id={Thread.CurrentThread.ManagedThreadId.ToString("00")}---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}");            {                //NoReturnNoAwait();                NoReturn();                for (int i = 0; i < 10; i++)                {                    Thread.Sleep(300);                    Console.WriteLine($"main thread task managedthreadid={Thread.CurrentThread.ManagedThreadId.ToString("00")}---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}--i={i}");                }            }        }        private static async void NoReturn()        {            //主线程执行            Console.WriteLine($"NoReturn sleep before await ,threadid={Thread.CurrentThread.ManagedThreadId.ToString("00")}---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}");            TaskFactory taskFactory = new TaskFactory();            Task task = taskFactory.StartNew(() =>             {                Console.WriteLine($"NoReturn sleep before  ,threadid={Thread.CurrentThread.ManagedThreadId.ToString("00")}---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}");                Thread.Sleep(300);                Console.WriteLine($"NoReturn sleep after  ,threadid={Thread.CurrentThread.ManagedThreadId.ToString("00")}---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}");            });            await task;            Console.WriteLine($"NoReturn sleep after await ,threadid={Thread.CurrentThread.ManagedThreadId.ToString("00")}---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}");        }        private static async void NoReturnNoAwait()        {                        //主线程执行            Console.WriteLine($"NoReturnNoAwait sleep before task ,threadid={Thread.CurrentThread.ManagedThreadId.ToString("00")}---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}");            Task task = Task.Run(() =>            {                Console.WriteLine($"NoReturnNoAwait sleep before  ,threadid={Thread.CurrentThread.ManagedThreadId.ToString("00")}---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}");                Thread.Sleep(300);                Console.WriteLine($"NoReturnNoAwait sleep after  ,threadid={Thread.CurrentThread.ManagedThreadId.ToString("00")}---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}");            });            Console.WriteLine($"NoReturnNoAwait sleep after task ,threadid={Thread.CurrentThread.ManagedThreadId.ToString("00")}---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}");        }

九、双色球项目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.代码

知识点
1.7个独立任务,要多线程计算,启动7个线程后,线程内存while一直计算
2.子线程不能更新界面,所以要this.Updatelbl(lbl, sNumber)实现
3.通过while (this.isgoon)从外面终止7个线程
4.通过lock (llock)对7个子线程进行加锁,避免7个线程同一时刻的值是一样的
5.子线程等待,更新界面 if (!this.isexsit(“00”) && !this.blue.Text.Equals(“00”))
6.所有子线程都执行完后回调taskFactory.ContinueWhenAll(this.tasklist.ToArray(), t => this.ShowResult() );//

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Windows.Forms;namespace 双色球{    public partial class Form1 : Form    {        public Form1()        {            InitializeComponent();            this.start.Enabled = true;            this.stop.Enabled = false;        }        private string[] rednums = {             "01","02","03","04","05","06","07","08","09","10",            "11","12","13","14","15","16","17","18","19","20",            "21","22","23","24","25","26","27","28","29","30",            "31","32","33"        };        private string[] bluenums = {            "01","02","03","04","05","06","07","08","09","10",            "11","12","13","14","15","16"        };        private static readonly object llock =new object();        private bool isgoon = true;        private List<Task> tasklist = new List<Task>();        private void start_Click(object sender, EventArgs e)        {            try            {                this.start.Text = "运行ing";                this.start.Enabled = false;                this.isgoon = true;                this.tasklist = new List<Task>();                this.blue.Text = "00";                this.label1.Text = "00";                this.label2.Text = "00";                this.label3.Text = "00";                this.label4.Text = "00";                this.label5.Text = "00";                this.label6.Text = "00";                Console.WriteLine(new Random().Next(0, 15));                Console.WriteLine(new Random().Next(0, 15));                Console.WriteLine(new Random().Next(0, 15));                Console.WriteLine(new Random().Next(0, 15));                Thread.Sleep(1000);                TaskFactory taskFactory = new TaskFactory();                 foreach(var control in this.groupBox1.Controls)                {                    if (control is Label)//标签中                    {                        Label lbl = (Label)control;                        if (lbl.Name.Contains("blue")) //blue                        {                           tasklist.Add( taskFactory.StartNew(() =>{    while (this.isgoon)    {        int indexNum1 = Getrandombnumlong(0, bluenums.Length);        string sNumber = this.bluenums[indexNum1];        // lbl.Text = sNumber;        this.Updatelbl(lbl, sNumber);    }}));                        }                        else//red                        {tasklist.Add( taskFactory.StartNew(() =>{    while (this.isgoon)    {            int indexNum1 = Getrandombnumlong(0, this.rednums.Length);            string sNumber = this.rednums[indexNum1];        // lbl.Text = sNumber;        lock (llock)        {            if (this.isexsit(sNumber))//加锁防止random出现一样的值            {                continue;//重复数据时放弃更新            }            this.Updatelbl(lbl, sNumber);//7个线程访问的是内存中同一个string sNumber,加锁防止取到的值是重复的,        }    }}));                        }                    }                }                //Thread.Sleep(3000);//直接等3000ms让stop开关enable,不靠谱,有可能有的线程因为数据重复,text没有更新                //this.stop.Enabled = true;                                Task.Run(()=> {                    while (true)                {                    Thread.Sleep(1000);                    if (!this.isexsit("00") && !this.blue.Text.Equals("00"))                    {this.Invoke(new Action(()=>{    this.stop.Enabled = true;//子线程操控不了主线程控件,需要主线程来完成}));                    break;                    }                }                });                taskFactory.ContinueWhenAll(this.tasklist.ToArray(), t => this.ShowResult() );//所有子线程都执行完            }            catch(Exception ex)            {                Console.WriteLine("双色球启动出现异常:{0}",ex.Message);            }        }        private void stop_Click(object sender, EventArgs e)        {            this.start.Enabled = true;            this.stop.Enabled = false;            this.isgoon = false;            //Task.WaitAll(this.tasklist.ToArray());//主线程等着全部任务完成,子任务还需要主线程干活更新label,所以又是死锁            //this.ShowResult();        }        private void ShowResult()        {            MessageBox.Show(string.Format("本期双色球为:{0} {1} {2} {3} {4} {5}   蓝球{6}"                , this.label1.Text                , this.label2.Text                , this.label3.Text                , this.label4.Text                , this.label5.Text                , this.label6.Text                , this.blue.Text     ));        }        //更新界面        private void Updatelbl(Label lbl ,string text)        {            if (lbl.InvokeRequired)            {                //这里的this指的是winform窗体主UI线程,让UI线程去更新text值                this.Invoke(new Action(()=>{                    //if (this.isgoon) //不延迟,点了就不更新                   // {                     lbl.Text = text;                    Console.WriteLine($"当前update线程id{Thread.CurrentThread.ManagedThreadId}");                   // }                }));            }            else            {                lbl.Text = text;            }        }        //验证标签中的text是否有相同的值        private bool isexsit(string snumber)        {            foreach (var control in this.groupBox1.Controls)            {                if (control is Label)//标签中的                {                    Label lbl = (Label)control;                    if (lbl.Name.Contains("label"))                    {                        if (lbl.Text.Equals(snumber))                        {return true;                        }                    }                }            }            return false;        }        public int Getrandombnumlong(int min , int max)        {            int indexNum = new Random().Next(min, max);            Thread.Sleep(1000);            return indexNum;        }    }}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

十、知识点代码汇总

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;namespace multithread{    public class Class1    {        private void dosomething(string name)        {            Console.WriteLine($"[****Dosomething {name} start: 线程号:({Thread.CurrentThread.ManagedThreadId.ToString("00")})---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}*******]");        }        //        //Console.WriteLine($"[------------到这里计算完成: 线程号:({Thread.CurrentThread.ManagedThreadId.ToString("00")})---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}-----]");        private void mainpoints() {            //1委托调用            Action<string> action = this.dosomething;//委托带参数            Action action1 = () => this.dosomething("CC");//委托不带参数            action.Invoke("AA");//同步调用委托            action("BB");//同步调用委托            action.BeginInvoke("cc", null, null);//异步调用委托            for (int i = 0; i < 5; i++)            {                string name = string.Format($"btn_click_{i}");                action.BeginInvoke(name, null, null);//异步多线程            }            List<Task> tasklist = new List<Task>();            TaskFactory taskFactory = new TaskFactory();            string name1 = string.Format($"btn_click");            CancellationTokenSource cts = new CancellationTokenSource();            Action<object> act = t =>            {                if (t.ToString().Equals("btn_click_11"))                {                    throw new Exception(string.Format($"{t}执行失败"));                }            };            tasklist.Add(taskFactory.StartNew(act, name1, cts.Token));            //2.委托执行完后进行回调            //标准写法            AsyncCallback callback = new AsyncCallback(i => Console.WriteLine($"[------------到这里计算完成: 线程号:({Thread.CurrentThread.ManagedThreadId.ToString("00")})---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}-----]"));            //简单写法            AsyncCallback callback1 = i =>           {               Console.WriteLine($"[------------到这里计算完成: 线程号:({Thread.CurrentThread.ManagedThreadId.ToString("00")})---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}-----]");           };            action.BeginInvoke("cc", callback, null);            //回调1 -异步action执行完才会执行回调-action.BeginInvoke("cc", callback, "nimen")-1            IAsyncResult asyncResult = null;            asyncResult = action.BeginInvoke("cc", callback, "nimen");            //回调1 - 异步action执行完才会执行回调 - action.BeginInvoke("cc", callback, "nimen")-2            action.BeginInvoke("cc", r =>            {                Console.WriteLine("11");            }, "nimen");            //回调2 -异步action执行完才会执行回调-(!asyncResult.IsCompleted)            while (!asyncResult.IsCompleted)            {                Console.WriteLine($"文件上传99.9%..");            }            //回调3 -异步action执行完才会执行回调--信号量WaitOne()            asyncResult.AsyncWaitHandle.WaitOne();//等待异步任务完成后,才打印计算完成            asyncResult.AsyncWaitHandle.WaitOne(2000);//限时等待            // 回调4 - 异步action执行完才会执行回调 - EndInvoke拿到委托函数的返回值            Func<int> func = () =>            {                return DateTime.Now.Day;            };            Console.WriteLine($"func.Invoke()={ func.Invoke()}");            IAsyncResult asyncResult1 = func.BeginInvoke(r =>            {                Console.WriteLine(r.AsyncState);            }, "nimen");            Console.WriteLine($"func.EndInvoke={ func.EndInvoke(asyncResult1)}");            //3.thread            //3.1.线程启动 thread.Start();            ThreadStart threadStart = () => this.dosomething("cc");            Thread thread = new Thread(threadStart);            thread.Start();            //3.2.线等待程thread.Join();            thread.Join(500);//卡主线程            Console.WriteLine($"等待500ms");            thread.Join();            //3.3.thread.ThreadState /thread.IsBackfround            while (thread.ThreadState != ThreadState.Stopped)            {                Thread.Sleep(100);//cpu时间片交出去干其他的事,但是内存还是占用            }            thread.IsBackground = true;//前台线程,当软件闪退时,会吐出日志            //4.threadPool            //4.1ThreadPool.GetMaxThreads            ThreadPool.QueueUserWorkItem(t =>                           { this.dosomething("cc");   this.dosomething("dd");                           });//接收一个没有返回值的委托            ThreadPool.SetMaxThreads(16, 16);            ThreadPool.GetMaxThreads(out int Workerthreads, out int completionPortThreads);            Console.WriteLine($"Workerthreads:{Workerthreads}+completionPortThreads{completionPortThreads}");            //4.2.manualResetEvent            ManualResetEvent manualResetEvent = new ManualResetEvent(false);            ThreadPool.QueueUserWorkItem(t =>            {                this.dosomething("cc");                manualResetEvent.Set();            });//接收一个没有返回值的委托            manualResetEvent.WaitOne();            Console.WriteLine($"等待ThreadPool.QueueUserWorkItem执行完再执行");            //5.task            Task.Run(() =>                {                    this.dosomething("cc");                    Console.WriteLine($"等待ThreadPool.QueueUserWorkItem执行完再执行");                });            new Task(() => this.dosomething("33")).Start();            TaskFactory taskFactory1 = Task.Factory;            taskFactory.StartNew(() => this.dosomething("44"));            //5.1 task.waitall、waitany  .ContinueWith taskFactory.ContinueWhenAny            List<Task> tasklist1 = new List<Task>();            tasklist.Add(Task.Run(() => this.dosomething("33")));            tasklist.Add(Task.Run(() => this.dosomething("33")));            Task.WaitAny(tasklist.ToArray());            Task.WaitAll(tasklist.ToArray());            Task.WhenAll(tasklist.ToArray()).ContinueWith(t =>            {                Console.WriteLine($"等待ThreadPool.QueueUserWorkItem执行完再执行");            });            taskFactory.ContinueWhenAny(tasklist.ToArray(), t => { });            //5.2 task线程完成标识            Task task = new Task(t => { }, "CC");            Console.WriteLine(task.AsyncState);//会打印CC            //5.3thread.sleep()卡线程 task.delay()不卡线程            //5.4tasklist线程取消            CancellationTokenSource cts1 = new CancellationTokenSource();            tasklist.Add(taskFactory.StartNew(() => this.dosomething("44"), cts1.Token));            //6.parallel启动多线程            Parallel.Invoke(                () => this.dosomething("11"),                () => this.dosomething("22"),                () => this.dosomething("33")                );            //6.1Parallel.For            Parallel.For(0, 5, i => this.dosomething(i));            Parallel.ForEach(new string[] { "0","1","2","3"},i=>this.dosomething("11"));            //6.2控制并发数量            ParallelOptions parallelOptions = new ParallelOptions();            parallelOptions.MaxDegreeOfParallelism = 3;            Parallel.For(0,40,parallelOptions,(i,state)=> {                     if (i==2)                {                    state.Break();                    state.Stop();                }            });            //7.线程安全lock            //private static readonly object btn_click = new object();            int c = 0;            tasklist.Add(taskFactory.StartNew(() => {                int m = 3 + 2;                lock (btn_click)                {                    c += 1;                }                        }));            //8.await/asyncawait 后的代码相当于回调,只不过不是自己写的,是编译器状态机自带的。            //回调方法continuewith是子线程完成的,但await不仅仅是回调(可子线程可主线程,计算机分配),所以他们又有所不同            private static async void Async()            {               await Task.Run(() =>                {                 Console.WriteLine($"等待ThreadPool.QueueUserWorkItem执行完再执行");               });                Console.WriteLine($"等待ThreadPool.QueueUserWorkItem执行完再执行");            }        }    }}

来源地址:https://blog.csdn.net/m0_46204224/article/details/131756149

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

c#多线程—基础概念到“双色球”项目实现(附知识点目录、代码、视频)

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

c#多线程—基础概念到“双色球”项目实现(附知识点目录、代码、视频)

总结:视频中对于多线程讲的非常透彻,从线程基础概念—>.net不同版本出现的线程方法—>多线程常出现问题—>双色球项目实践,每个知识点都有代码实操,受益匪浅。附上学习笔记和实操代码。 视频 目录 一、线程、进程概念及优缺点二、四种异
2023-08-30

编程热搜

目录