多线程学习笔记2
主要内容:Thread的API使用 ThreadPool线程池的使用
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 多线程学习2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btn_Thread_Click(object sender, EventArgs e)
{
Console.WriteLine($"btn_Thread_Click Start {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
Action action = () => this.DoSomethingLong("btnThread_Click");
ThreadStart threadStart = () => this.DoSomethingLong("btnThread_Click");
Thread thread = new Thread(threadStart);
thread.Start();
//Thread不带返回值
//thread.Suspend();//线程暂停执行(挂起)目前已经不使用这种方式了
//thread.Resume();//线程唤醒 目前已经不使用这种方式了
//try
//{
// thread.Abort();//线程销毁,方式是抛异常。也不建议使用,不一定即使,并且有些命令执行了就停不下来,
//}
//catch(Exception ex)
//{
// //
// Thread.ResetAbort();//取消异常继续计算
//}
//如果用的就需要使用try catch,捕获异常
//以上三种方法不推荐使用
//线程等待
//thread.Join();//当前线程等待thread完成
Console.WriteLine("等待500ms");
thread.Join(500);//最多等500ms
while(thread.ThreadState==ThreadState.Stopped)
{
Thread.Sleep(100);//当前线程休息100ms
}
Console.WriteLine(thread.IsBackground); //默认是前台线程,启动之后一定要完成任务,才退出
thread.IsBackground = true;//后台线程,随着进程退出
thread.Priority = ThreadPriority.Highest;//线程优先级,CPU会优先执行等级较高的线程,但不是先只执行优先级最高的,还是同时执行,用处不是很大
this.ThreadWithCallback(() => Console.WriteLine($"这是action {Thread.CurrentThread.ManagedThreadId.ToString("00")}"),
() => Console.WriteLine($"这是callback {Thread.CurrentThread.ManagedThreadId.ToString("00")}"));
Func<int> func = this.ThreadWithReturn<int>(() =>
{
Thread.Sleep(2000);
return DateTime.Now.Millisecond;
});
Console.WriteLine("子线程执行完毕");
int iResult = func.Invoke();
Console.WriteLine(iResult);
Console.WriteLine($"btn_Thread_Click End {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
}
private void DoSomethingLong(string str)
{
for(int i=1;i<10;i++)
{
Thread.Sleep(200);
}
Console.WriteLine(str + " " + Thread.CurrentThread.ManagedThreadId.ToString("00"));
}
//启动子线程计算--完成委托后,该线程去执行后续回调委托
private void ThreadWithCallback(Action act, Action callback)
{
Thread thread = new Thread(() =>
{
act.Invoke();
callback.Invoke();
});
thread.Start();
}
//带返回值的异步调用,需要获取返回值
private Func<T> ThreadWithReturn<T>(Func<T> func)
{
T t = default(T);
Thread thread = new Thread(() =>
{
t = func.Invoke();
});
thread.Start();
return () =>
{
while (thread.ThreadState != ThreadState.Stopped)
{
Thread.Sleep(200);
}
//thread.Join();等待线程结束
return t;
};
}
private void btn_ThreadPool_Click(object sender, EventArgs e)
{
Console.WriteLine($"btn_ThreadPool_Clickk Start {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
//threadpool出现的原因 1 提供了太多的API,很难使用;2 无限使用线程,加以限制;3 重用线程,避免重复的创建和销毁
ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));//启动线程
//获取线程池的最大数目,工作线程和异步线程
int workerThreads, completionPortThreads;
ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);
Console.WriteLine($"workerThreads={workerThreads} completionPortThreads={completionPortThreads}");
//获取线程池的最小数目
ThreadPool.GetMinThreads(out workerThreads, out completionPortThreads);
Console.WriteLine($"workerThreads={workerThreads} completionPortThreads={completionPortThreads}");
ThreadPool.SetMaxThreads(32, 32);//设置最大线程数
ThreadPool.SetMinThreads(4, 4);//设置最小线程数
ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);
Console.WriteLine($"workerThreads={workerThreads} completionPortThreads={completionPortThreads}");
ThreadPool.GetMinThreads(out workerThreads, out completionPortThreads);
Console.WriteLine($"workerThreads={workerThreads} completionPortThreads={completionPortThreads}");
//ThreadPool没有直接对线程的操作,
//ThreadPool线程等待的方法
//类,包含一个bool属性
//false--WaitOne等待--Set--true--WaitOne直接过去
//true--WaitOne直接过去--Reset--false--WaitOne等待
ManualResetEvent manualResetEvent = new ManualResetEvent(false);//可以保证线程安全,相比与自己创建的bool变量
ThreadPool.QueueUserWorkItem(t =>
{
this.DoSomethingLong("btn_ThreadPool_Click");
manualResetEvent.Set();
//manualResetEvent.Reset();
});
manualResetEvent.WaitOne();
manualResetEvent.Reset();//设置为false
//一般情况下不要阻塞线程池的线程:错误实例
//之前设置了线程池的最大数量为16,下面的程序阻塞了16个线程后程序就会卡死
for(int i=0;i<20;i++)
{
int k = i;
ThreadPool.QueueUserWorkItem(t =>
{
Console.WriteLine(k);
if(k<18)
{
manualResetEvent.WaitOne();
}
else
{
manualResetEvent.Set();//设置为true
}
});
}
if (manualResetEvent.WaitOne())
{
Console.WriteLine("没有锁死......");
}
Console.WriteLine("ThreadPool.QueueUserWorkItem执行完成后才执行");
//线程重用
ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));
ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));
ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));
ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));
ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));
Thread.Sleep(10 * 1000);
ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));
ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));
ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));
ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));
ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));
Console.WriteLine($"btn_ThreadPool_Click End {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
}
}
}