1 Star 0 Fork 1

Run2948/AspNetCore.Thread.Project

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
Form1.cs 22.15 KB
一键复制 编辑 原始数据 按行查看 历史
Run2948 提交于 2021-07-26 12:55 . 避开多线程的坑
using System;
using System.Collections.Concurrent;
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 Zhaoxi.ThreadShow
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
#region 多线程:Thread:
/// <summary>
/// 多线程:Thread:
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ThreadBtn_Click(object sender, EventArgs e)
{
Console.WriteLine($"****************ThreadBtn_Click Start ThreadId: {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
//多线程就是从这里开始的
//Thread thread = new Thread(() => Console.WriteLine("欢迎大家来到高级本的体验课!"));
//Thread thread = new Thread(() =>
//{
// this.DoCostTimeMethod("fresh");
//});
//thread.Start();//开启了一个线程
{
//Thread thread = new Thread(o => Console.WriteLine($"这里是开启了一个线程 {Thread.CurrentThread.ManagedThreadId.ToString("00")} 结果为:{o}"));
//thread.Start("Joer2鹏");
}
{
//thread.Suspend();//暂停
//thread.Resume();//让暂停的线程继续执行。。。
//thread.Abort();//线程要终止
//Thread.ResetAbort();//终止的线程可以继续运行
//Thread.Sleep(2000); //主线程等待2秒钟;
//thread.Join();//thread等待等待 代码执行到这里会卡住
//thread.Join(2000); //限时等待 过时不候
//while (thread.ThreadState!=ThreadState.Stopped)
//{
// Thread.Sleep(2000);
//}
//thread.Priority = ThreadPriority.Highest;//最好不通过他来控制线程 只能从概念上来增加他的优先级
//thread.IsBackground = true;//进程关闭 线程也就随之取消
//thread.IsBackground = false;
}
{
//While await 他会卡顿界面;
//Thread 没有线程的Api来控制线程顺序
//使用多线程:不会卡顿界面;
//关于委托的详解:大家添加一下课堂的助教微信 有专门的委托课程分享;
//Action threadStart = new Action(() =>
//{
// this.DoCostTimeMethod("fresh");
//});
//Action action = () => Console.WriteLine("这是上一个线程执行完毕以后执行的动作");
//this.ThreadWithCallBack(threadStart, action);
////如果我需要返回值呢?
Func<int> func = () =>
{
return DateTime.Now.Year;
};
//int iResult = ThreadWithReturn(func);
Func<int> fResult = ThreadWithReturn(func);
Console.WriteLine("this is ....");
Console.WriteLine("this is ....");
Console.WriteLine("this is ....");
int iResult = fResult.Invoke();
}
Console.WriteLine($"****************ThreadBtn_Click End ThreadId: {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
}
/// <summary>
/// 如何保证不卡顿界面;让两个委托中的任务有序执行?
/// </summary>
/// <param name="threadStart"></param>
/// <param name="action"></param>
private void ThreadWithCallBack(Action threadStart, Action action)
{
///在这里开启一个线程去执行这两个委托
ThreadStart start = () =>
{
threadStart.Invoke();
action.Invoke();
};
new Thread(start).Start();
}
private Func<T> ThreadWithReturn<T>(Func<T> func)
{
T t = default(T);
ThreadStart threadStart = () =>
{
t = func.Invoke();
};
Thread thread = new Thread(threadStart);
thread.Start();
return new Func<T>(() =>
{
thread.Join();
return t;
});
}
/// <summary>
/// 单纯的只是一个比较耗时的方法
/// </summary>
/// <param name="name"></param>
private void DoCostTimeMethod(string name)
{
Console.WriteLine($"****************DoCostTimeMethod Start {name} ThreadId: {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
long lResult = 0;
for (int i = 0; i < 1_000_000_000; i++)
{
lResult += i;
}
Thread.Sleep(5000);
Console.WriteLine($"****************DoCostTimeMethod End {name} ThreadId: {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} {lResult}***************");
}
#endregion
#region 线程池 ThreadPool
/// <summary>
/// 线程池:ThreadPool
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ThreadPoolBtn_Click(object sender, EventArgs e)
{
Console.WriteLine($"****************ThreadPoolBtn_Click Start ThreadId: {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
{
//WaitCallback waitCallback = new WaitCallback(o =>
//{
// this.DoCostTimeMethod(o.ToString()) ;
//});
//ThreadPool.QueueUserWorkItem(waitCallback,"极限。。。");//从线程池中获取线程
}
{
ManualResetEvent mre = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(o =>
{
Console.WriteLine($"this is {o}");
mre.Set();
});//从线程池中获取线程
//线程等待
mre.WaitOne();
}
Console.WriteLine($"****************ThreadPoolBtn_Click End ThreadId: {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
}
#endregion
#region 多线程Task
/// <summary>
/// C#中的多线程Task
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void TaskBtn_Click(object sender, EventArgs e)
{
Console.WriteLine($"****************TaskBtn_Click Start ThreadId: {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
{ //如何启动线程呢?
//{
// Task task = new Task(() => { Console.WriteLine($"this id thrad {Thread.CurrentThread.ManagedThreadId.ToString("00")}"); });
// task.Start();
//}
//{
// TaskFactory taskfactory = new TaskFactory();
// taskfactory.StartNew(() =>
// {
// DoCostTimeMethod("Joker2鹏");
// });
//}
}
{ // 申请一个线程
//ThreadPool.SetMaxThreads(8, 8);//设置最大线程数量;因为线程池里的线程是全局
//如何去控制线程数量呢?
//List<int> threadIds = new List<int>();
//List<Task> tasklist = new List<Task>();
//for (int i = 0; i < 50; i++)
//{
// tasklist.Add(Task.Run(() => { //申请一个线程
// threadIds.Add(Thread.CurrentThread.ManagedThreadId);
// Console.WriteLine($" ThreadId:{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
// }));
//}
//Task.WaitAll(tasklist.ToArray());//阻塞主线程等待所有子线程完成任务
//int iResult = threadIds.Distinct().Count();//iResult=8 Task from ThradPool
}
{
//每一期高级班当学完内容以后我们最后会有几个项目落地;项目分为很多功能模块
//讲课能不能多线程?
//1.Richard 老师给讲课 高级班学习中 不能多线程
//2.学习结束后,同学配合开发项目 可以多线程线程吗?可以多线程;、
//分为小组;5个人
//直接就是一个同学一个线程嘛!
{
{
//List<Task> taskList = new List<Task>();
//TeachShow("核心语法特训");
//TeachShow("MVC框架深解析");
//TeachShow(".NetCore 跨平台开发");
//TeachShow("分布式架构的搭建");
//TeachShow("微服务架构的搭建");
//TeachShow("EF/EFCore");
//Console.WriteLine("高级班学习完成。。。准备去开发项目");
//TaskFactory taskFactory = Task.Factory;
////Thread.Sleep(1000);
/////不会阻塞主线程
//taskList.Add(taskFactory.StartNew(() => CodingShow("fresh", "后台框架的搭建")));
//taskList.Add(taskFactory.StartNew(() => CodingShow("马启新", "微服务架构的搭建")));
//taskList.Add(taskFactory.StartNew(() => CodingShow("Joker2鹏", "微信接口")));
//taskList.Add(taskFactory.StartNew(() => CodingShow("Single", "Core环境搭建。。")));
//{
// //// Task.WaitAll 可以等待所有子线程完成任务以后继续往后执行;但是会卡顿界面;
// //Task.WaitAll(taskList.ToArray());// 主线程等待所有子线程完成任务
// ////高级班的学员都不错,所有模块开发完毕以后,我们准备聚个餐 K 个歌。。。
// //Console.WriteLine("所有模块开发完毕以后,我们准备聚个餐 K 个歌。。。");
//}
//{
// ///回调:就在一堆任务执行完毕以后,去申请一个新的线程来执行新的动作
// //taskFactory.ContinueWhenAll(taskList.ToArray(), t => Console.WriteLine($"所有模块开发完毕以后,我们准备聚个餐 K 个歌。。。"));
// taskFactory.ContinueWhenAny(taskList.ToArray(), t => Console.WriteLine($"XXX同学开发完成以后,Ricahr 老师就准备环境部署。。。"));
//}
}
//如何控制线程数量;
//为什么要限制线程数量;申请线程执行任务也是需要耗费资源;
{
/////如果把线程控制在20个线程以内
//List<Task> taskList = new List<Task>();
//for (int i = 0; i < 10000; i++)
//{
// if (taskList.Count(t => t.Status == TaskStatus.Running) >= 20)
// {
// Task.WaitAny(taskList.ToArray());//阻塞主线程 等待一个任务执行完成
// taskList = taskList.Where(t => t.Status != TaskStatus.RanToCompletion && t.Status != TaskStatus.Canceled && t.Status != TaskStatus.Faulted).ToList();
// }
// taskList.Add(Task.Run(() =>
// {
// Thread.Sleep(1000);
// Console.WriteLine("this is Open");
// }));
// Console.WriteLine($"Thrad Count={taskList.Count()}");
//}
}
{//如果新申请的线程里面有返回值怎么获取呢?
Func<int> func = () =>
{
Thread.Sleep(3000);
return DateTime.Now.Year;
};
Task<int> task = new Task<int>(func);
task.Start();
int iResult = task.Result; //这里会阻塞页面的;
}
}
}
Console.WriteLine($"****************TaskBtn_Click End ThreadId: {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
}
/// <summary>
/// 单线程调用方法 讲课的方法
/// </summary>
/// <param name="lesson"></param>
private void TeachShow(string lesson)
{
Console.WriteLine($"{lesson}开始讲。。。 ThreadId:{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
long lResult = 0;
//for (int i = 0; i < 1_000_000_000; i++)
//{
// lResult += i;
//}
Console.WriteLine($"{lesson}讲完了。。。ThreadId:{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
}
/// <summary>
/// 模拟Coding过程
/// </summary>
/// <param name="name"></param>
/// <param name="projectName"></param>
private void CodingShow(string name, string projectName)
{
Console.WriteLine($"****************CodingShow Start {name} {projectName} {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
long lResult = 0;
for (int i = 0; i < 1_000_000_000; i++)
{
lResult += i;
}
Console.WriteLine($"****************CodingShow End {name} {projectName} {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} {lResult}***************");
}
#endregion
/// <summary>
/// 多线程中的那些坑儿
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void AsyncCorebtn_Click(object sender, EventArgs e)
{
Console.WriteLine($"****************AsyncCorebtn_Click Start ThreadId: {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
#region 多线程异常处理
{
//1.单线程中如何处理异常? try-catch
//多线程内部如果发生异常之后,就直接吞掉;
//2.Task.WaitAll(taskList.ToArray()可以捕捉到线程内部的异常
//List<Task> taskList = new List<Task>();
//for (int i = 0; i < 20; i++)
//{
// try
// {
// string str = $"AsyncCorebtn_Click_{i}";
// taskList.Add(Task.Run(() =>
// {
// Console.WriteLine($"{str} Strat {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
// if (str.Equals("AsyncCorebtn_Click_8"))
// {
// throw new Exception("AsyncCorebtn_Click_8异常了。。。");
// }
// else if (str.Equals("AsyncCorebtn_Click_11"))
// {
// throw new Exception("AsyncCorebtn_Click_11。。。");
// }
// else if (str.Equals("AsyncCorebtn_Click_15"))
// {
// throw new Exception("AsyncCorebtn_Click_15。。。");
// }
// Console.WriteLine($"{str} end {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
// }));
// Task.WaitAll(taskList.ToArray());
// }
// catch (AggregateException exa)//异常匹配是先具体 再抽象
// {
// foreach (var exception in exa.InnerExceptions)
// {
// Console.WriteLine(exception.Message);
// }
// }
// catch (Exception ex)
// {
// Console.WriteLine(ex.Message);
// }
//}
}
//再实际开发中,如果多个线程去处理业务,如果有一个线程发生异常之后,我们其实更希望让其他别的线程能够停下来!
#endregion
//1.定义一个中间值/不安全
//2.CancellationTokenSource 有一个IsCancellationRequested bool值,默认为false; 同时提供一个Cancel() 方法用来充值有一个IsCancellationRequested false--true
//3.线程不能从外部终止,只能自己终止自己!
//4.CancellationTokenSource+业务判断实现线程取消
//既然需要线程取消;正常情况能不能让还没有开启的线程直接就不开启了?
//
//Thread thread = null;
//thread.Abort();
#region 线程取消
{
//CancellationTokenSource cts = new CancellationTokenSource();
////bool isOk = true;
//for (int i = 0; i < 200; i++)
//{
// string str = $"AsyncCorebtn_Click_{i}";
// Task.Run(() =>
// {
// Thread.Sleep(new Random().Next(10 * 5, 10 * 10));
// try
// {
// Console.WriteLine($"{str} start..");
// if (str.Equals("AsyncCorebtn_Click_8"))
// {
// throw new Exception("AsyncCorebtn_Click_8异常了。。。");
// }
// if (cts.IsCancellationRequested == false)
// {
// Console.WriteLine("AsyncCorebtn_Click_ end....");
// }
// else
// {
// Console.WriteLine("AsyncCorebtn_Click_ 取消....");
// }
// }
// catch (Exception ex)
// {
// cts.Cancel();//IsCancellationRequested false--true
// }
// }, cts.Token);
//}
}
#endregion
#region 临时变量
{
////for (int i = 0; i < 20; i++)
////{
//// Task.Run(() => Console.WriteLine($"this is {i}"));
////}
////申请线程 不阻塞,延迟执行。。。
////js闭包
//for (int i = 0; i < 20; i++)
//{
// int k = i;
// Task.Run(() => Console.WriteLine($"this is {i} _{k}"));
//}
}
#endregion
//线程安全:如果你的代码在进程中有多个线程同时运行这一段,如果每次运行的结果都跟单线程运行时的结果一致,那么就是线程安全的
//线程安全问题:一般都是有全局变量/共享变量/静态变量/硬盘文件/数据库的值,只要多线程都能访问和修改
///怎么解决呢?
///1.lock
///2.避免去操作同一个变量
///3.线程安全对象
//现在大家提提问;
#region 线程安全&lock
{
{
Num = 0;
for (int i = 0; i < 10000; i++)
{
Num++;
}
Console.WriteLine($"Num is {Num}");
}
{
//AsyncNum 一定再0-10000之间
List<Task> tasks = new List<Task>();
AsyncNum = 0;
for (int i = 0; i < 10000; i++)
{
tasks.Add(Task.Run(() =>
{
lock (obj_Lock) //反多线程 相当于单线程了
{
AsyncNum++;
}
}));
}
Task.WaitAll(tasks.ToArray());
Console.WriteLine($"AsyncNum is {AsyncNum}");
}
//线程死锁 明天晚上我准备给大家分享一个多线程的实战;
}
#endregion
Console.WriteLine($"****************AsyncCorebtn_Click End ThreadId: {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
}
private static readonly object obj_Lock = new object();
private int Num = 0;
private int AsyncNum = 0;
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/Run2948/asp-net-core.-thread.-project.git
git@gitee.com:Run2948/asp-net-core.-thread.-project.git
Run2948
asp-net-core.-thread.-project
AspNetCore.Thread.Project
master

搜索帮助