C#基础--线程Thread和线程池ThreadPool

C#基础–线程Thread和线程池ThreadPool

一、线程 Thread

1. 开启一个线程

ThreadStart 是属于System.Threading 中的一个内置委托

ThreadStart threadStart = () =>
{
    this.DoSomethingLong("btnThread_Click");
};

Thread thread = new Thread(threadStart);	//传入委托
thread.Start(); //开启一个新线程  

ParameterizedThreadStart 是属于System.Threading 中的一个内置委托

ParameterizedThreadStart threadStart = ar =>
{
    this.DoSomethingLong("btnThread_Click");
};
Thread thread = new Thread(threadStart);
thread.Start(); //开启一个新线程

2. 暂停/恢复线程

无法实时的去 “暂停 ” 或者 “恢复” 线程,因为线程是由系统调度执行的,而且中间存在一个延时现象,不可能直接帮你执行

thread.Suspend();	// 暂停线程
thread.Resume();	//恢复  无法实时的去暂停或者恢复线程 

3. 终结线程

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

Thread.ResetAbort() 也会存在一定的延迟问题

thread.Abort();	//终结线程
Thread.ResetAbort();	//终结的线程继续执行

4. 等待任务

根据线程状态等待

ThreadState 是一种枚举类型

while (thread.ThreadState != ThreadState.Stopped)
{
    Thread.Sleep(200);
}

Join等待

限时等待,和委托中的 WaitOne等待 很像

thread.Join();	//无限时等待
thread.Join(2000); 	//最多等待2000毫秒

5. 线程调度优先级

Priority 是一种枚举类型,设置了的话只是增加它的优先概率,并不能一定能保证它实现正确的优先级执行(因为CPU是分核的)

thread.Priority = ThreadPriority.Highest;

6. 后台/前台线程

后台线程:进程结束,线程也结束;例如,winform 功能在控制台输出,关闭winform窗体,控制台窗口也会立即关闭

前台线程:进程结束后,任务执行完毕以后,线程才结束;例如,winform 功能在控制台输出,关闭winform窗体,控制台窗口只有等线程任务完成后才会关闭

thread.IsBackground = true;	//后台线程  进程结束,线程结束了
thread.IsBackground = false; //前台线程   进程结束后,任务执行完毕以后,线程才结束 

二、线程 Thread 扩展

1. 无返回结果

 private void ThreadWithCallBack(ThreadStart threadStart, Action actionCallback)
 {
     ThreadStart threadStart = new ThreadStart(() =>
                                                {
                                                    threadStart.Invoke();
                                                    actionCallback.Invoke();
                                                });
     Thread thread = new Thread(threadStart);
     thread.Start();
 }
ThreadStart threadStart1 = () =>
{
    Console.WriteLine("执行任务");
};
Action action = () =>
{
    Console.WriteLine("执行回调");
};
this.ThreadWithCallBack(threadStart1, action);

2. 开启一个线程,并获取返回结果

  • 扩展方法内部开启一个线程执行任务 – 执行传入的委托

  • 线程等待的工作封装到另外一个委托,将委托返回出去,让外部执行:这样就不会造成封装方法内阻塞(卡界面),调用封装方法的程序可以继续执行之后的代码

  • 需要结果的时候,再去执行返回的委托;如果不需要的结果的话,就不必再去执行返回的委托了

/// <summary>
/// 既要不卡界面,又需要返回结果  
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="func"></param>
/// <returns></returns>
private Func<T> ThreadWithReturn<T>(Func<T> func)
{
    T t = default(T);
    ThreadStart threadStart = new ThreadStart(() =>
                                              {
                                                  t = func.Invoke();
                                              });
    Thread thread = new Thread(threadStart);
    thread.Start();

    return new Func<T>(() =>
                       {
                           thread.Join();
                           return t;
                       });
}
Func<int> func = () =>
                    {
                        Thread.Sleep(5000);
                        return DateTime.Now.Year;
                    };
Func<int> FuncResult = this.ThreadWithReturn(func);
Console.WriteLine("同步执行操作1--发短信");
Console.WriteLine("同步执行操作2--发邮件");
Console.WriteLine("同步执行操作3--统计信息");
Console.WriteLine("同步执行操作4--更新ES数据"); 
int iResult = FuncResult.Invoke();  //如果需要得到执行结果,是必须要等待的

三、线程池 ThreadPool

.NetFramework2.0 出现的

在Thread中对线程的管理需要我们自己去从操作,在不断的开启线程和销毁中,存在很大的开销,为了让线程可以反复的使用,出现了池化思想!

线程池不仅可以节省资源,还可以控制线程总数量,防止滥用!

1. 开启一个线程

ThreadPool.QueueUserWorkItem 需要传入一个WaitCallback委托作为参数

WaitCallback是 System.Threading 内置的一个委托

ThreadPool.QueueUserWorkItem(o =>
                             {
                                 this.DoSomethingLong("ThreadPool.QueueUserWorkItem1");	//开启了一个线程
                             });
ThreadPool.QueueUserWorkItem(o =>
                             {
                                 Console.WriteLine($"第二个参数:{o}");
                                 this.DoSomethingLong("ThreadPool.QueueUserWorkItem1");//开启了一个线程
                             }, "Hyl");

image-20220327202912971

2. 设置/获取 最大最小线程

设置线程数量是全局,线程池是全局,Task、async/awit 都是来自于线程,所以本人不建议大家随便设置!

设置线程最大数量的时候,数量不能低于本计算机的核数,否则设置无效。如下图效果图:(2047,1000 是默认设置)

ThreadPool.SetMaxThreads(2, 2); //这里在设置的时候,数量不能低于本计算机的 核数
ThreadPool.SetMinThreads(2, 2);

ThreadPool.GetMaxThreads(out int maxWorkerThreads1, out int maxCompletionPortThreads1);
ThreadPool.GetMinThreads(out int minWorkerThreads1, out int minCompletionPortThreads1);

Console.WriteLine($"当前电脑最大workerThreads={maxWorkerThreads1},最大的completionPortThreads={maxCompletionPortThreads1}");
Console.WriteLine($"当前电脑最小workerThreads={minWorkerThreads1},最小的completionPortThreads={minCompletionPortThreads1}");

image-20220327203351858

3. 线程等待

ManualResetEvent manualResetEvent = new ManualResetEvent(false); //开关关闭 
ThreadPool.QueueUserWorkItem(o =>
                             {
                                 this.DoSomethingLong("btnThreadPool_Click1");
                                 Thread.Sleep(3000);
                                 manualResetEvent.Set();// 开关打开
                             });
manualResetEvent.WaitOne();	//执行到这儿来的时候,我就等你给我发信号
Console.WriteLine("计算完成");

image-20220327204628068

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YSの陈憨憨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值