一:引言
/// .NetFramework1.0就有多线程!
/// 进程:计算机概念,程序运行在服务器占据的全部计算机的资源
/// 线程:计算机概念,是进程在相应操作时候的一个最小单元,也包括cpu/硬盘/内存 虚拟概念
/// 进程和线程:包含关系,线程是属于某一个进程的,如果一个进程销毁,线程也就不会存在。
/// 句柄:描述程序中的某一个最小单元,是一个long数字,操作系统通过这个数字识别应用程序。
/// 多线程:计算概念,就是某一个进程中,多个线程同时运行;
///
/// C#中的多线程:
/// Thread类是C#语言对线程对象一个封装;
///
/// 为什么可以多线程呢?
///
/// 1、Cpu有多个核;可以并行计算;
/// 双核四线:这里的线程是模拟核;
///
/// 2、cpu分片:某1s的处理能切分成1000份,操作系统调度去相应不同的任务;
/// 从宏观角度来说:感觉就有多个任务在并发执行;
/// 从微观角度来说:一个物理cpu不能在某一刻为某一个任务服务
///
/// 同步异步:
/// 同步方法:发起调用,只有在调用的方法完成以后,才能继续执行一下一行代码,按照顺序执行;
/// 诚心请吃饭,我请你吃饭,你说你现在需要忙一会儿,我等你,等你忙完了以后,咱们一起去吃饭。
///
/// 异步方法:发起调用,不等待完成,直接进入下一行代码的执行,启动一个新的线程来完成计算
///
/// 客气一下请人吃饭:我请你吃饭,你说你现在需要忙一会儿,我就不等你了,我自己先去吃饭了,你忙完以后,自己去吃饭。
二:同步和异步的比较
#region Sync
private void btnSync_Click(object sender, EventArgs e)
{
Console.WriteLine($"****************btnSync_Click Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
int l = 3;
int m = 4;
int n = l + m;
for (int i = 0; i < 5; i++)
{
string name = string.Format($"btnSync_Click_{i}");
this.DoSomethingLong(name);
}
Console.WriteLine($"****************btnSync_Click End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
}
#endregion
#region Async
private void btnAsync_Click(object sender, EventArgs e)
{
Console.WriteLine($"****************btnAsync_Click Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
Action<string> action = this.DoSomethingLong;
for (int i = 0; i < 5; i++)
{
action.BeginInvoke("btnAsync_Click", null, null);
}
Console.WriteLine($"****************btnAsync_Click End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
}
#endregion
#region Private Method
private void DoSomethingLong(string name)
{
Console.WriteLine($"****************DoSomethingLong Start {name} {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
long lResult = 0;
Thread.Sleep(2000);
Console.WriteLine($"****************DoSomethingLong End {name} {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} {lResult}***************");
}
#endregion
private void btnAsyncAdvanced_Click(object sender, EventArgs e)
{
Console.WriteLine($"****************btnAsyncAdvanced_Click Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
IAsyncResult asyncResult = null;
AsyncCallback callback = ar =>
{
Thread.Sleep(5000);
Console.WriteLine($"这里是beginInvoke的第三个参数{ar.AsyncState}");
Console.WriteLine(object.ReferenceEquals(ar, asyncResult));
Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy - MM - dd HH: mm:ss.fff")}");
Console.WriteLine("计算结束");
};
{
Action<string> action = this.DoSomethingLong;
asyncResult = action.BeginInvoke("btnAsyncAdvanced_Click", callback, "八万公里");
{
int i = 0;
while (!asyncResult.IsCompleted)
{
if (i < 9)
{
Console.WriteLine($"正在玩命为你加载中。。。已经完成{++i * 10}%");
}
else
{
Console.WriteLine($"正在玩命为你加载中。。。已经完成99.9999%");
}
Thread.Sleep(200);
}
Console.WriteLine("加载完成。。。");
}
asyncResult.AsyncWaitHandle.WaitOne();
asyncResult.AsyncWaitHandle.WaitOne(-1);
asyncResult.AsyncWaitHandle.WaitOne(3000);
{
Func<int> func = () =>
{
return DateTime.Now.Year;
};
func.Invoke();
IAsyncResult asyncResult1 = func.BeginInvoke(ar =>
{
func.EndInvoke(ar);
}, null);
int iResult = func.EndInvoke(asyncResult1);
Console.WriteLine(iResult);
}
Console.WriteLine($"****************btnAsyncAdvanced_Click End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} ***************");
}
三:.NetFramework1.0(Thread)
{
ParameterizedThreadStart threadStart = ar =>
{
this.DoSomethingLong("btnThread_Click");
Console.WriteLine($"****************btnThread_Click End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} ***************");
};
Thread thread = new Thread(threadStart);
thread.Start();
}
{
ThreadStart threadStart = () =>
{
Thread.Sleep(5000);
this.DoSomethingLong("btnThread_Click");
Console.WriteLine($"****************btnThread_Click End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} ***************");
};
Thread thread = new Thread(threadStart);
thread.Start();
thread.Suspend();
thread.Resume();
thread.Abort();
Thread.ResetAbort();
while (thread.ThreadState != ThreadState.Stopped)
{
Thread.Sleep(200);
}
thread.Join();
thread.Join(2000);
thread.Priority = ThreadPriority.Highest;
thread.IsBackground = true;
thread.IsBackground = false;
{
ThreadStart threadStart1 = () =>
{
Console.WriteLine($"****************btnThread_Click End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} ***************");
Thread.Sleep(3000);
};
Action action = () =>
{
Console.WriteLine($"****************btnThread_Click End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} ***************");
Thread.Sleep(3000);
};
this.ThreadWithCallBack(threadStart1, action);
}
{
Func<int> func = () =>
{
Thread.Sleep(5000);
return DateTime.Now.Year;
};
Func<int> FuncResult = this.ThreadWithReturn(func);
int iResult = FuncResult.Invoke();
}
}
private void ThreadWithCallBack(ThreadStart threadStart, Action actionCallback)
{
ThreadStart threadStart1 = new ThreadStart(() =>
{
threadStart.Invoke();
actionCallback.Invoke();
});
Thread thread = new Thread(threadStart1);
thread.Start();
}
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;
});
}
四:.NetFramework2.0(ThreadPool)
private void btnThreadPool_Click(object sender, EventArgs e)
{
Console.WriteLine($"****************btnThreadPool_Click Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
{
ThreadPool.QueueUserWorkItem(o =>
{
Console.WriteLine($"**************** {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
this.DoSomethingLong("ThreadPool.QueueUserWorkItem1");
});
}
{
ThreadPool.QueueUserWorkItem(o =>
{
Console.WriteLine($"第二个参数:{o}");
this.DoSomethingLong("ThreadPool.QueueUserWorkItem1");
}, "Hyl");
}
{
ThreadPool.GetMaxThreads(out int maxWorkerThreads, out int maxCompletionPortThreads);
ThreadPool.GetMinThreads(out int minWorkerThreads, out int minCompletionPortThreads);
Console.WriteLine($"当前电脑最大workerThreads={maxWorkerThreads},最大的completionPortThreads={maxCompletionPortThreads}");
Console.WriteLine($"当前电脑最小workerThreads={minWorkerThreads},最小的completionPortThreads={minCompletionPortThreads}");
Console.WriteLine("设置线程数量之后:");
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}");
}
{
ManualResetEvent manualResetEvent = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(o =>
{
this.DoSomethingLong("btnThreadPool_Click1");
Thread.Sleep(3000);
manualResetEvent.Set();
});
manualResetEvent.WaitOne();
Console.WriteLine("计算完成");
}
{
ThreadPool.SetMaxThreads(8, 8);
ManualResetEvent manualResetEvent = new ManualResetEvent(false);
for (int i = 0; i < 10; i++)
{
int k = i;
ThreadPool.QueueUserWorkItem(t =>
{
Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
if (k == 9)
{
manualResetEvent.Set();
}
else
{
manualResetEvent.WaitOne();
}
});
}
if (manualResetEvent.WaitOne())
{
Console.WriteLine("执行成功!");
}
}
Console.WriteLine($"****************btnThreadPool_Click End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} ***************");
}
五:.NetFramework3.0(Task)
private void btntask_Click(object sender, EventArgs e)
{
Console.WriteLine($"****************btnThreadPool_Click Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
{
Task task = new Task(() =>
{
this.DoSomethingLong("btntask_Click1");
});
task.Start();
}
{
Task.Run(() =>
{
this.DoSomethingLong("btntask_Click2");
});
}
{
TaskFactory taskFactory = Task.Factory;
taskFactory.StartNew(() =>
{
this.DoSomethingLong("btntask_Click3");
});
}
{
Thread thread = new Thread(() => {
Console.WriteLine("开启了一个新线程"); });
thread.Start();
ThreadPool.QueueUserWorkItem(o => {
Console.WriteLine("开启了一个新线程"); });
}
{
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
Thread.Sleep(2000);
stopwatch.Stop();
Console.WriteLine($"{stopwatch.ElapsedMilliseconds}");
}
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
Task task = Task.Delay(2000).ContinueWith(t =>
{
stopwatch.Stop();
Console.WriteLine($"{stopwatch.ElapsedMilliseconds}");
Console.WriteLine("回调已完成");
});
}
}
{
List<Task> tasksList = new List<Task>();
TaskFactory taskFactory = new TaskFactory();
tasksList.Add(taskFactory.StartNew(() => {
this.Coding("001", "系统管理"); }));
tasksList.Add(taskFactory.StartNew(() => {
this.Coding("002", "部门管理"); }));
tasksList.Add(taskFactory.StartNew(() => {
this.Coding("003", "客户管理"); }));
tasksList.Add(taskFactory.StartNew(() => {
this.Coding("004", "接口管理"); }));
tasksList.Add(taskFactory.StartNew(() => {
this.Coding("005", "写Api"); }));
Task.WaitAny(tasksList.ToArray());
Task.WaitAll(tasksList.ToArray());
}
Console.WriteLine($"****************btnThreadPool_Click End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} ***************");
}
六:.NetFramework4.5(Parallel )
private void btnParallel_Click(object sender, EventArgs e)
{
Console.WriteLine($"**************** btnParallel_Click Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} ***************");
{
Parallel.Invoke(() => {
this.DoSomethingLong("btnParallel_Click_1"); },
() => {
this.DoSomethingLong("btnParallel_Click_2"); },
() => {
this.DoSomethingLong("btnParallel_Click_3"); },
() => {
this.DoSomethingLong("btnParallel_Click_4"); },
() => {
this.DoSomethingLong("btnParallel_Click_5"); });
}
{
ParallelOptions parallelOptions = new ParallelOptions();
parallelOptions.MaxDegreeOfParallelism = 2;
Parallel.For(0, 10, parallelOptions, t => this.DoSomethingLong($"btnParallel_Click_{t}"));
}
{
ParallelOptions parallelOptions = new ParallelOptions();
parallelOptions.MaxDegreeOfParallelism = 2;
Parallel.ForEach(new int[] {
12, 13, 14, 15, 16, 17 }, parallelOptions, t => this.DoSomethingLong($"btnParallel_Click_{t}"));
}
Console.WriteLine($"**************** btnParallel_Click End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} ***************");
}
七:多线程异常处理和异常取消
private void btnThreadCore_Click(object sender, EventArgs e)
{
Console.WriteLine($"**************** btnThreadCore_Click Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} ***************");
#region 多线程异常处理
{
Thread thread = new Thread('执行方法');
thread.Abort();
try
{
List<Task> taskList = new List<Task>();
for (int i = 0; i < 100; i++)
{
string name = $"btnThreadCore_Click_{i}";
int k = i;
taskList.Add(Task.Run(() =>
{
if (k == 5)
{
throw new Exception($"{name} 异常了");
}
else if (k == 6)
{
throw new Exception($"{name} 异常了");
}
else if (k == 10)
{
throw new Exception($"{name} 异常了");
}
Console.WriteLine($"this is {name} Ok!");
}));
};
Task.WaitAll(taskList.ToArray());
}
catch (AggregateException aex)
{
foreach (var exception in aex.InnerExceptions)
{
Console.WriteLine(exception.Message);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
}
#endregion
#region 线程取消
{
CancellationTokenSource cts = new CancellationTokenSource();
try
{
List<Task> taskList = new List<Task>();
for (int i = 0; i < 100; i++)
{
string name = $"btnThreadCore_Click_{i}";
int k = i;
taskList.Add(Task.Run(() =>
{
if (k == 5)
{
throw new Exception($"{name} 异常了");
}
if (!cts.IsCancellationRequested)
{
Console.WriteLine($"this is {name} Ok!");
}
else
{
Console.WriteLine($"this is {name} Stop!");
}
}));
};
Task.WaitAll(taskList.ToArray());
}
catch (AggregateException aex)
{
cts.Cancel();
foreach (var exception in aex.InnerExceptions)
{
Console.WriteLine(exception.Message);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
}
#endregion
Console.WriteLine($"**************** btnThreadCore_Click End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} ***************");
}
八:多线程安全问题
private static readonly object Obj_Lock = new object();
for (int i = 0; i < 100000; i++)
{
this.NumOne += 1;
}
for (int i = 0; i < 100000; i++)
{
Task.Run(() =>
{
try
{
lock (Obj_Lock )
{
this.NumTow += 1;
}
}
catch (Exception)
{
throw;
}
});
}
public class RandomHelper
{
public int GetRandomNumberDelay(int min, int max)
{
Thread.Sleep(this.GetRandomNumber(500, 1000));
return this.GetRandomNumber(min, max);
}
public int GetRandomNumber(int min, int max)
{
Guid guid = Guid.NewGuid();
string sGuid = guid.ToString();
int seed = DateTime.Now.Millisecond;
for (int i = 0; i < sGuid.Length; i++)
{
switch (sGuid[i])
{
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
seed = seed + 1;
break;
case 'h':
case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
seed = seed + 2;
break;
case 'o':
case 'p':
case 'q':
case 'r':
case 's':
case 't':
seed = seed + 3;
break;
case 'u':
case 'v':
case 'w':
case 'x':
case 'y':
case 'z':
seed = seed + 3;
break;
default:
seed = seed + 4;
break;
}
}
Random random = new Random(seed);
return random.Next(min, max);
}
}
九:最终版(async/await)
public class AwaitAsyncClass
{
public async static void TestShow()
{
Test();
}
private async static Task Test()
{
Console.WriteLine($"当前主线程id={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
{
Task t = NoReturnTask();
Console.WriteLine($"Main Thread Task ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
t.Wait();
await t;
}
{
Task<long> t = SumAsync();
Console.WriteLine($"Main Thread Task ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
long lResult = t.Result;
t.Wait();
}
{
Task<int> t = SumFactory();
Console.WriteLine($"Main Thread Task ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
long lResult = t.Result;
t.Wait();
}
Console.WriteLine($"Main Thread Task ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
Console.Read();
}
private static async Task NoReturnTask()
{
Console.WriteLine($"NoReturnTask Sleep before await,ThreadId={Thread.CurrentThread.ManagedThreadId}");
Task task = Task.Run(() =>
{
Console.WriteLine($"NoReturnTask Sleep3000 before,ThreadId={Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(3000);
Console.WriteLine($"NoReturnTask Sleep3000 after,ThreadId={Thread.CurrentThread.ManagedThreadId}");
});
await task;
Console.WriteLine($"NoReturnTask Sleep after await,ThreadId={Thread.CurrentThread.ManagedThreadId}");
}
private static async Task<long> SumAsync()
{
Console.WriteLine($"SumAsync 111 start ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
long result = 0;
await Task.Run(() =>
{
for (int k = 0; k < 10; k++)
{
Console.WriteLine($"SumAsync {k} await Task.Run ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(1000);
}
for (long i = 0; i < 999_999_999; i++)
{
result += i;
}
});
Console.WriteLine($"SumFactory 111 end ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
await Task.Run(() =>
{
for (int k = 0; k < 10; k++)
{
Console.WriteLine($"SumAsync {k} await Task.Run ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(1000);
}
for (long i = 0; i < 999999999; i++)
{
result += i;
}
});
Console.WriteLine($"SumFactory 111 end ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
await Task.Run(() =>
{
for (int k = 0; k < 10; k++)
{
Console.WriteLine($"SumAsync {k} await Task.Run ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(1000);
}
for (long i = 0; i < 999999999; i++)
{
result += i;
}
});
Console.WriteLine($"SumFactory 111 end ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
return result;
}
private static Task<int> SumFactory()
{
Console.WriteLine($"SumFactory 111 start ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
TaskFactory taskFactory = new TaskFactory();
Task<int> iResult = taskFactory.StartNew<int>(() =>
{
Thread.Sleep(3000);
Console.WriteLine($"SumFactory 123 Task.Run ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
return 123;
});
Console.WriteLine($"SumFactory 111 end ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
return iResult;
}
}