Summary: The video explains multi-threading very thoroughly, from the basic concepts of threads -> Threading methods that appear in different versions of .net -> Common problems with multi-threading -> Shuangseqiu project practice, every knowledge point has code practice, you will benefit from it Very shallow. Attached are study notes and practical code.
video
Table of contents
- 1. Concepts of threads and processes and their advantages and disadvantages
- 2. Four asynchronous waiting methods
- 3. Thread object of .net1.0 basic version
- 4. net 2.0 threadpool
- 5. .net3.0 task
-
- 1.Task thread startup
- 2.waitall and waitany will block the main thread interface.
- 3.task.whenall.continuewith()
- 4.taskfactory.continuewith()
- 5. Designed to have only 11 threads working at most
- 6. After taskfactory detects which thread has ended, it returns the thread ID
- 7. Tasks can be nested multiple times to avoid blocking the main thread.
- 8. Two waitalls are executed in sequence
- 9.thread.sleep() thread stuck task.delay() does not stuck thread
- 10.Task thread completion identification
- 6. .net4.5 parallel
- 7. Threadcore
- 八、.net.0 await/async
- 9. Double Color Ball Project
- 10. Summary of knowledge point codes
1. Concepts of threads and processes and their advantages and disadvantages
Thread: The smallest unit of program execution. All operations are completed by threads. When synchronization is used, resources are always occupied by this thread, so other interfaces cannot work, and the interface will be stuck.
1. The start is uncontrollable. 2. The end is uncontrollable.
A time-consuming (i++) and resource-consuming (thread.sleep) method
2. Four asynchronous waiting methods
1. Asynchronous control waiting-callback callback
After the action is executed, asyncResult and "nimen" are passed to the callback as parameters.
2. Asynchronous control waiting-asyncResult.IsCompleted
3. Asynchronous control waits for WaitOne()-semaphore
4. Asynchronous control waits for endinvoke-gets the return value of the asynchronous function
5. Video lesson code 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")}-----]");
/*1调用委托
{
Action<string> action = this.dosomething;
action.Invoke("AA");//同步调用委托
action("BB");//同步调用委托
action.BeginInvoke("cc", null, null);//异步调用委托
}
/*2异步-不可控
{
Action<string> action = this.dosomething;
for (int i = 0; i < 5; i++)
{
string name = string.Format($"btn_click_{i}");
action.BeginInvoke(name, null, null);//异步调用委托
}
}*/
/*3.异步不可控
{
Action<string> action = this.dosomething;
action.BeginInvoke("cc", null, null);
Console.WriteLine($"[------------到这里计算完成: 线程号:({Thread.CurrentThread.ManagedThreadId.ToString("00")})---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}-----]");
}*/
/*4.异步等待1-回调
{
Action<string> action = this.dosomething;
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);
}*/
/*5.异步等待1-回调解析(action执行完将asyncResult、"nimen"当成参数传给callback)-不卡界面
{
Action<string> action = this.dosomething;
IAsyncResult asyncResult = null;
AsyncCallback callback = i =>
{
Console.WriteLine(object.ReferenceEquals(asyncResult , i));
Console.WriteLine(i.AsyncState);
Console.WriteLine($"[------------到这里计算完成: 线程号:({Thread.CurrentThread.ManagedThreadId.ToString("00")})---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}-----]");
};
asyncResult = action.BeginInvoke("cc", callback, "nimen");
}
*/
/*6.异步等待2 asyncResult.IsCompleted-回调解析-while函数卡界面
{
Action<string> action = this.dosomething;
IAsyncResult asyncResult = null;
AsyncCallback callback = i =>
{
Console.WriteLine(object.ReferenceEquals(asyncResult, i));
Console.WriteLine(i.AsyncState);
Console.WriteLine($"[------------到这里计算完成: 线程号:({Thread.CurrentThread.ManagedThreadId.ToString("00")})---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}-----]");
};
asyncResult = action.BeginInvoke("cc", callback, "nimen");
int a = 0;
while (!asyncResult.IsCompleted)
{
if (a < 10)
{
Console.WriteLine($"文件上传{a++ * 10}%..");
Console.WriteLine($"线程号:({Thread.CurrentThread.ManagedThreadId.ToString("00")})---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}");
}
else
{
Console.WriteLine($"文件上传99.9%..");
}
Thread.Sleep(200);
}
}*/
/*7.异步等待3-WaitOne()-信号量3
{
Action<string> action = this.dosomething;
IAsyncResult asyncResult = action.BeginInvoke("cc", null, null);
Console.WriteLine("dosomething");
Console.WriteLine("dosomething");
asyncResult.AsyncWaitHandle.WaitOne();//等待异步任务完成后,才打印计算完成
asyncResult.AsyncWaitHandle.WaitOne(2000);//限时等待
Console.WriteLine($"[------------到这里计算完成: 线程号:({Thread.CurrentThread.ManagedThreadId.ToString("00")})---{System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}-----]");
}*/
/*.8异步等待4endinvoke-拿到委托函数的返回值
{
Action<string> action = this.dosomething;
Func<int> func = () =>
{
Thread.Sleep(2000);
return DateTime.Now.Day;
};
Console.WriteLine($"func.Invoke()={ func.Invoke()}");
IAsyncResult asyncResult=func.BeginInvoke(r =>
{
Console.WriteLine(r.AsyncState);
}, "nimen");
Console.WriteLine($"func.EndInvoke={ func.EndInvoke(asyncResult)}");
Console.WriteLine($"[------------到这里计算完成: 线程号:({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}*******]");
}
}
}
3. Thread object of .net1.0 basic version
1. Thread startup
{
//Action<string> 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), other people's threads are waiting for it for 500ms. At this time, there are two threads in the project. One is waiting for 500ms, and the other is running
thread.sleep(500). It is the own thread that hands over the CPU time slice. Go out to do other things, but the memory is still occupied.
The foreground thread sleeps for 500ms. When the software crashes, the log will be spit out.
4. net 2.0 threadpool
1. Thread startup and setting the maximum number of threads in the thread pool
2.manualResetEvent.WaitOne() asynchronous control waiting
{
ManualResetEvent manualResetEvent = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(t =>
{
this.dosomething("cc");
manualResetEvent.Set();
});//接收一个没有返回值的委托
manualResetEvent.WaitOne();
Console.WriteLine($"等待ThreadPool.QueueUserWorkItem执行完再执行");
}
The risk of waitone() is that if no thread is available, it will get stuck.
3. Handwritten asynchronous callback function
4. Delegate asynchronous call with return value (French structure to be learned)
5. .net3.0 task
1.Task thread startup
2.waitall and waitany will block the main thread interface.
waitall, waitany application scenarios
3.task.whenall.continuewith()
First, task.whenall is not stuck on the main interface and ends quickly. btn_task_click is the main thread task.
Secondly, continuewith(). When the thread in the tasklist is executed and the conditions are met (all\any), the following commissions are executed directly in sequence, similar to the callback such as "smug smile"
4.taskfactory.continuewith()
5. Designed to have only 11 threads working at most
6. After taskfactory detects which thread has ended, it returns the thread ID
7. Tasks can be nested multiple times to avoid blocking the main thread.
8. Two waitalls are executed in sequence
If there are two waitalls that need to be executed but they are in different threads, but the order of the two waitalls must be guaranteed, the solution is to add the first waitall to the tasklist, and then let the waitall of the second task judge.
9.thread.sleep() thread stuck task.delay() does not stuck thread
10.Task thread completion identification
6. .net4.5 parallel
1.parallel starts multi-threading
2.Parallel thread stops
7. Threadcore
1.Exception handling
An exception in the main thread will cause the program to crash if no one manages it.
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. Thread cancellation
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
{
/*
if (cts.IsCancellationRequested)
{
Console.WriteLine("{0}取消一个任务的执行",t);
}*/
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}执行失败"));
}
/*
else
{
Console.WriteLine("{0}执行成功", 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. Multi-threaded temporary variables
4. Thread-safe lock (the lock locks the reference)
4.1 Thread safety issues
4.2 Thread-shared variables have thread safety issues
4.3Lock principle
Only one thread can enter, there is no concurrency, solving the problem but sacrificing performance.
It is recommended to use Microsoft-defined locks
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;
/*
//非多线程
this.TotalCount += 1;
this.IntList.Add(newI);*/
//多线程
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 principle
The code after await is equivalent to a callback, but it is not written by yourself, but comes with the compiler state machine.
The callback method continuewith is completed by the child thread, but await is not just a callback (it can be allocated by the child thread, the main thread, or the computer), so they are different.
1.1 Principles of small code testing
2. Async methods with and without return values
2.1 only asynic
2.2asynic\await appears in pairs
Await should be followed by a method with a return value.
When defining a method, with the async and await suite, although the method does not have a return, this method can also be regarded as having a return value.
Do not use return value
Use the return value
2.3 The difference between t.Wait() and await t
2.4await decompilation-equivalent to state machine
3. The code of this knowledge point
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")}");
}
9. Double Color Ball Project
1.Code
Knowledge points
1. 7 independent tasks require multi-thread calculation. After starting 7 threads, the thread memory while keeps calculating
2. The child thread cannot update the interface, so this.Updatelbl(lbl, sNumber) is required to implement
3. Through while (this.isgoon) from Terminate 7 threads outside
4. Lock the 7 sub-threads through lock (llock) to prevent the 7 threads from having the same value at the same time
5. The sub-threads wait and update the interface if (!this.isexsit(“00”) && !this.blue.Text.Equals(“00”))
6. After all sub-threads have finished executing, call back 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;
/*
while (true)
{
Thread.Sleep(1000);
if (!this.isexsit("00") && !this.blue.Text.Equals("00"))
{
this.stop.Enabled = true;
break;
}
}*/
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;
}
}
}
10. Summary of knowledge point codes
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执行完再执行");
}
}
}
}