c# 多线程使用总结


线程:Thread类是C#语言对线程对象的一个封装;
4核8进程:模拟核,一个CPU每秒10亿次计算,可以分成多个片,每个片可被一个线程使用
CPU分片:操作系统把:CPU分片,一个物理CPU同时只能为一个任务服务;

同步方法:发起调用,执行完后依次执行下一个任务
异步方法:任何一个异步多线程离不开委托,发起调用,启动一个新的线程来完成任务;
Action<string> action= this.DoSomething;
action.BeginInvoke("btn");

1.同步方法卡界面,主线程忙与计算,无暇他姑;异步方法不卡,主线程闲置,计算任务交给子任务;
可以改善用户体验,web应用发短信通知,启动异步多线程去完成;

卡界面,慢,启动有序/不卡,快,启动无序;
资源换性能 :
1.资源不是无限的;
2.资源调度损耗;
3.所有线程并不是越多越好;

程序向线程池发线程请求,线程池向操作系统请求资源,安排不同的CUP片调度处理
多线程由时间先后顺序要求的,要特别小心,不能通过延时,预估来估计;

并行:多核之间叫并行
并发:CPU分片的并发;同一时间做多个事

CPU * 4

async
2.判断多线程执行完成的方法;
1.回调callback;
2.asyncResult.IsComleted
3.WaitOne:asyncResult.AsyncWaitHandle.WaitOne()
4.EndInvoke(asyncResult)

private void TestThread( )
{

//Action<string> action = this.DoSomethingLong;

////1 回调:将后续动作通过回调参数传递进去,子线程完成计算后,去调用这个回调委托
IAsyncResult asyncResult = null;//是对异步调用操作的描述
AsyncCallback callback = ar =>
{
Console.WriteLine($"{object.ReferenceEquals(ar, asyncResult)}");
Console.WriteLine($"btnAsyncAdvanced_Click计算成功了。{ar.AsyncState}。{Thread.CurrentThread.ManagedThreadId.ToString("00")}");
};
asyncResult = action.BeginInvoke("btnAsyncAdvanced_Click", callback, "aa");

//2 通过IsComplate等待,卡界面--主线程在等待,边等待边提示
//( Thread.Sleep(200);位置变了,少了一句99.9999)
int i = 0;
while (!asyncResult.IsCompleted)
{
if (i < 9)
{
Console.WriteLine($"中华民族复兴完成{++i * 10}%....");
}
else
{
Console.WriteLine($"中华民族复兴完成99.999999%....");
}
Thread.Sleep(200);
}
Console.WriteLine("中华民族复兴已完成,沉睡的东方雄狮已觉醒!");

// 3 WaitOne等待,即时等待 限时等待
asyncResult.AsyncWaitHandle.WaitOne();//直接等待任务完成
asyncResult.AsyncWaitHandle.WaitOne(-1);//一直等待任务完成
asyncResult.AsyncWaitHandle.WaitOne(1000);//最多等待1000ms,超时就不等了

//4 EndInvoke 即时等待, 而且可以获取委托的返回值 一个异步操作只能End一次
action.EndInvoke(asyncResult);//等待某次异步调用操作结束

Console.WriteLine("全部计算成功了。。");

Func<int> func = () =>
{
Thread.Sleep(2000);
return DateTime.Now.Hour;
};
int iResult = func.Invoke();//22
IAsyncResult asyncResult = func.BeginInvoke(ar =>
{
//int iEndResultIn = func.EndInvoke(ar);
}, null);
int iEndResult = func.EndInvoke(asyncResult);//22

Console.WriteLine($"****************btnAsync_Click End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
}

----------------------task------------------------------------------

1 thread:线程等待,回调,前台线程/后台线程
2 threadpool:线程池使用,设置线程池,ManualResetEvent
3 扩展封装thread&threadpool回调/等待

1 Task:Waitall WaitAny Delay
2 TaskFactory:ContinueWhenAny ContinueWhenAll
3 并行运算Parallel.Invoke/For/Foreach
Thread
ThreadPool
ThreadPool.SetMaxThreads(8,8) 线程池是全局的,单例,同时并发8个;线程复用;
Task

.netframework3.0 task 基于线程池的,提供了丰富的API
Thread.Task

Task.Sleep(300)
Task
Thread.Sleep(2000);主线程等待2秒后在执行,卡画面;
Task.Delay(2000).ContinueWIth等待2秒后启动新线程执行,不影响主线程;
Task.Delay(2000).ContinueWIth(t=>{
//dosomething
});


1.什么时候使用多线程:任务能并发时
2.多线程好处:提升速度/优化体验
3.waitAll,waitAny
4.ContinueWhenAny(),ContinueWhenAll()

主线程等待所有动作完成后执行的动作:Task.WaitAll()
主线程等待任何一个动作完成后执行的动作:Task.WaitAny()

主线程等待所有动作完成后执行的动作:taskFactory.ContinueWhenAll()
主线程任何一个完成后执行的工作:taskFactory.ContinueWhenAny(),

Parall 并发执行多个action 多线程,主界面阻塞,主线程参入计算;
Parall.For() 能控制并发数量;
parall.Foreach()
parallelOption opt=new Paralleloptions():控制线程并发数量如3;