同步与异步多线程的区别:
1、同步方法卡界面(UI线程忙于计算);异步多线程不卡界面(主线程闲置,子线程在计算)
2、同步方法慢(CPU利用率低、资源耗费少);异步多线程快(CPU利用率高、资源耗费多)
3、同步方法是有序的;异步方法是无序的(启动无序、执行时间不确定、结束无序)
实现异步多线程的6种方式与取消多线程:
1、委托的异步调用
2、Thread实现多线程
3、Task实现多线程
4、ThreadPool实现多线程
5、Parallel实现多线程
6、async和await实现多线程
7、取消多线程
一、公共类库
public delegate void DoSomething();
public delegate int DoSomethingReturn();
public delegate void DoMore(int age, string name);
public delegate int DoMoreReturn(int age, string name);
public class CommonDelegate
{
public static void DoSomethingMethod()
{
Console.WriteLine("Sub-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(3000);
Console.WriteLine("Sub-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
public static int DoSomethingReturnMethod()
{
Console.WriteLine("Sub-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(3000);
Console.WriteLine("Sub-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
return 99;
}
public static void DoMoreMethod(int age, string name)
{
Console.WriteLine("Sub-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Console.WriteLine("age={0},name={1}", age, name);
Thread.Sleep(3000);
Console.WriteLine("Sub-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
public static int DoMoreReturnMethod(int age, string name)
{
Console.WriteLine("Sub-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Console.WriteLine("age={0},name={1}", age, name);
Thread.Sleep(3000);
Console.WriteLine("Sub-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
return 99;
}
}
二、delegate实现多线程
1、无参无返回值
private void btnNoParamNoReturn_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
DoSomething doSomething = new DoSomething(CommonDelegate.DoSomethingMethod);
doSomething.BeginInvoke(null, null);
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
2、无参有返回值
private void btnNoParamHasReturn_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
DoSomethingReturn doSomething = new DoSomethingReturn(CommonDelegate.DoSomethingReturnMethod);
IAsyncResult iasyncResult = doSomething.BeginInvoke(null, null);
int result = doSomething.EndInvoke(iasyncResult);
Console.WriteLine("result={0}", result);
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
3、 有参无返回值
private void btnHasParamNoReturn_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
DoMore doMore = new DoMore(CommonDelegate.DoMoreMethod);
doMore.BeginInvoke(16, "guo", null, null);
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
4、有参有返回值
private void btnHasParamHasReturn_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
DoMoreReturn doMoreReturn = new DoMoreReturn(CommonDelegate.DoMoreReturnMethod);
IAsyncResult iasyncResult = doMoreReturn.BeginInvoke(16, "guo", null, null);
int result = doMoreReturn.EndInvoke(iasyncResult);
Console.WriteLine("result={0}", result);
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
5、异步回调
private void btnCallback_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
DoMoreReturn doMore = new DoMoreReturn(CommonDelegate.DoMoreReturnMethod);
doMore.BeginInvoke(16, "guo", Callback, "wulala");
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
private void Callback(IAsyncResult iasyncResult)
{
Console.WriteLine("Callback-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
AsyncResult asyncResult = (AsyncResult)iasyncResult;
//获取回调方法的参数
string parameter = asyncResult.AsyncState.ToString();
//获取委托的返回值
DoMoreReturn doMore = (DoMoreReturn)asyncResult.AsyncDelegate;
int result = doMore.EndInvoke(asyncResult);
Thread.Sleep(3000);
Console.WriteLine("result={0},parameter={1}", result, parameter);
Console.WriteLine("Callback-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
6、WaitOne()操作
private void btnWaitOne_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
DoMore doMore = new DoMore(CommonDelegate.DoMoreMethod);
IAsyncResult iasyncResult = doMore.BeginInvoke(16, "guo", null, null);
//无参或参数为-1表示无限等等
//iasyncResult.AsyncWaitHandle.WaitOne();
//iasyncResult.AsyncWaitHandle.WaitOne(-1);
//表示等待1000ms
iasyncResult.AsyncWaitHandle.WaitOne(1000);
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
7、IsCompleted判断
private void btnIsCompleted_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
DoMoreReturn doMoreReturn = new DoMoreReturn(CommonDelegate.DoMoreReturnMethod);
IAsyncResult iasyncResult = doMoreReturn.BeginInvoke(16, "guo", null, null);
while (!iasyncResult.IsCompleted)
{
Console.WriteLine("正在执行......");
Thread.Sleep(1000);
}
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
三、Thread实现多线程
Thread默认是前台线程,主线程必须等待前台线程执行完毕后才能退出,thread可以设置为后台线程,适合长跑型的操作;ThreadPool默认是后台线程,主线程执行完毕后就能退出,无论后台线程是否执行完毕。ThreadPool是Thread基础上的一个线程池,目的是减少频繁创建销毁线程的开销,适合频繁、短期执行的小操作。
1、无参无返回值
private void btnNoParamNoReturn_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
ThreadStart threadStart = new ThreadStart(CommonDelegate.DoSomethingMethod);
Thread thread = new Thread(threadStart);
thread.Start();
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
2、无参有返回值
private void btnNoParamHasReturn_Click(object sender, EventArgs e)
{
//Thread默认不支持返回值
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Func<int> func = new Func<int>(CommonDelegate.DoSomethingReturnMethod);
Func<int> beginInvokeFunc = BeginInvoke<int>(func);
Console.WriteLine("Main-Other-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(2000);
Console.WriteLine("Main-Other-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
//想获取计算结果必须等待
int result = beginInvokeFunc.Invoke();
Console.WriteLine("result=" + result);
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
/// <summary>
/// 基于Thread封装一个支持返回值的方法
/// </summary>
/// <param name="threadStart"></param>
/// <param name="callback"></param>
private Func<T> BeginInvoke<T>(Func<T> func)
{
T t = default(T);
ThreadStart start = new ThreadStart(() =>
{
//func.Invoke()等价于func()表示同步执行
t = func.Invoke();
});
Thread thread = new Thread(start);
thread.Start();
return new Func<T>(() =>
{
thread.Join();
return t;
});
}
3、有参无返回值
private void btnHasParamNoReturn_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
//委托方法不能省略参数类型,lambda表达式可省略参数类型
ParameterizedThreadStart threadStart = new ParameterizedThreadStart(delegate (object name)
{
Console.WriteLine("Sub-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(3000);
Console.WriteLine("name={0}", name);
Console.WriteLine("Sub-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Thread thread = new Thread(threadStart);
//只能有一个object类型的参数
thread.Start("guo");
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
4、有参有返回值
private void btnHasParamHasReturn_Click(object sender, EventArgs e)
{
//Thread默认不支持返回值
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Func<int, string, int> func = new Func<int,string,int>(CommonDelegate.DoMoreReturnMethod);
Func<int> beginInvokeFunc = BeginInvoke<int>(func, 16, "guo");
Console.WriteLine("Main-Other-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(2000);
Console.WriteLine("Main-Other-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
//想获取计算结果必须等待
int result = beginInvokeFunc.Invoke();
Console.WriteLine("result=" + result);
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
/// <summary>
/// 基于Thread封装一个支持返回值的方法
/// </summary>
/// <param name="threadStart"></param>
/// <param name="callback"></param>
private Func<T> BeginInvoke<T>(Func<int, string,T> func,int age,string name)
{
T t = default(T);
ThreadStart start = new ThreadStart(() =>
{
//func.Invoke()等价于func()表示同步执行
t = func.Invoke(age, name);
});
Thread thread = new Thread(start);
thread.Start();
return new Func<T>(() =>
{
thread.Join();
return t;
});
}
5、异步回调
private void btnCallback_Click(object sender, EventArgs e)
{
//Thread默认不支持回调
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
ThreadStart threadStart = new ThreadStart(CommonDelegate.DoSomethingMethod);
Action callback = new Action(() =>
{
Console.WriteLine("Callback-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(3000);
Console.WriteLine("Callback-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
BeginInvoke(threadStart, callback);
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
/// <summary>
/// 基于Thread封装一个支持回调的方法
/// </summary>
/// <param name="threadStart"></param>
/// <param name="callback"></param>
private void BeginInvoke(ThreadStart threadStart,Action callback)
{
ThreadStart start = new ThreadStart(() =>
{
//threadStart.Invoke()等价于threadStart()表示同步执行
threadStart.Invoke();
callback.Invoke();
});
Thread thread = new Thread(start);
thread.Start();
}
四、Task实现多线程
1、Start启动(耗时任务可设置为TaskCreationOptions.LongRunning类型)
private void btnStart1_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
//如果任务比较耗时的话可以设置为LongRunning类型
Task task = new Task(CommonDelegate.DoSomethingMethod, TaskCreationOptions.LongRunning);
Task task = new Task(CommonDelegate.DoSomethingMethod);
task.Start();
Thread.Sleep(1000);
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
2、StartNew启动
private void btnStart2_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Task task = new TaskFactory().StartNew(CommonDelegate.DoSomethingMethod);
Thread.Sleep(1000);
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
3、Run启动
private void btnStart3_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Task task = Task.Run(new Action(CommonDelegate.DoSomethingMethod));
Thread.Sleep(1000);
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
4、ContinueWith控制任务顺序
private void btnContinueWith_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Task task = new Task(CommonDelegate.DoSomethingMethod);
//利用ContinueWith()为任务排序不会阻塞主线程
task.ContinueWith((a) =>
{
Console.WriteLine("ContinueWith-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(3000);
Console.WriteLine("ContinueWith-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
task.Start();
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
5、ContinueWhenAny操作
private void btnContinueWhenAny_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
TaskFactory taskFactory = new TaskFactory();
Task task1 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务1-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(1000);
Console.WriteLine("任务1-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task task2 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务2-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(3000);
Console.WriteLine("任务2-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task task3 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务3-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(5000);
Console.WriteLine("任务3-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
taskFactory.ContinueWhenAny(new Task[] { task1, task2, task3 }, (a) =>
{
Console.WriteLine("ContinueWhenAny-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(1000);
Console.WriteLine("ContinueWhenAny-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
6、ContinueWhenAll操作
private void btnContinueWhenAll_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
TaskFactory taskFactory = new TaskFactory();
Task task1 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务1-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(1000);
Console.WriteLine("任务1-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task task2 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务2-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(3000);
Console.WriteLine("任务2-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task task3 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务3-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(5000);
Console.WriteLine("任务3-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
taskFactory.ContinueWhenAll(new Task[] { task1, task2, task3 }, (a) =>
{
Console.WriteLine("ContinueWhenAll-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(1000);
Console.WriteLine("ContinueWhenAll-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
7、WaitAny操作
private void btnWaitAny_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
TaskFactory taskFactory = new TaskFactory();
Task task1 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务1-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(3000);
Console.WriteLine("任务1-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task task2 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务2-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(4000);
Console.WriteLine("任务2-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task task3 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务3-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(5000);
Console.WriteLine("任务3-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task.WaitAny(new Task[] { task1, task2, task3 });
Console.WriteLine("WaitAny执行之后【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
8、WaitAll操作
private void btnWaitAll_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
TaskFactory taskFactory = new TaskFactory();
Task task1 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务1-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(3000);
Console.WriteLine("任务1-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task task2 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务2-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(4000);
Console.WriteLine("任务2-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task task3 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务3-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(5000);
Console.WriteLine("任务3-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task.WaitAll(new Task[] { task1, task2, task3 });
Console.WriteLine("WaitAll执行之后【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
9、WaitAny自定义非阻塞操作
private void btnWaitAnyNoBlock_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
TaskFactory taskFactory = new TaskFactory();
Task task = taskFactory.StartNew(() =>
{
Task task1 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务1-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(3000);
Console.WriteLine("任务1-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task task2 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务2-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(4000);
Console.WriteLine("任务2-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task task3 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务3-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(5000);
Console.WriteLine("任务3-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task.WaitAny(new Task[] { task1, task2, task3 });
Console.WriteLine("WaitAny执行之后【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
10、 WaitAll自定义非阻塞操作
private void btnWaitAllNoBlock_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
TaskFactory taskFactory = new TaskFactory();
Task task = taskFactory.StartNew(() =>
{
Task task1 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务1-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(3000);
Console.WriteLine("任务1-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task task2 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务2-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(4000);
Console.WriteLine("任务2-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task task3 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务3-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(5000);
Console.WriteLine("任务3-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task.WaitAll(new Task[] { task1, task2, task3 });
Console.WriteLine("WaitAll执行之后【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
11、WhenAny操作
private void btnWhenAny_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
TaskFactory taskFactory = new TaskFactory();
Task task1 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务1-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(3000);
Console.WriteLine("任务1-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task task2 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务2-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(4000);
Console.WriteLine("任务2-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task task3 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务3-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(5000);
Console.WriteLine("任务3-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task task = Task.WhenAny(new Task[] { task1, task2, task3 });
task.ContinueWith((a) =>
{
Console.WriteLine("ContinueWith-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(3000);
Console.WriteLine("ContinueWith-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
12、WhenAll操作
private void btnWhenAll_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
TaskFactory taskFactory = new TaskFactory();
Task task1 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务1-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(3000);
Console.WriteLine("任务1-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task task2 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务2-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(4000);
Console.WriteLine("任务2-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task task3 = taskFactory.StartNew(() =>
{
Console.WriteLine("任务3-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(5000);
Console.WriteLine("任务3-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Task task = Task.WhenAll(new Task[] { task1, task2, task3 });
task.ContinueWith((a) =>
{
Console.WriteLine("ContinueWith-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(3000);
Console.WriteLine("ContinueWith-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
13、有参数有返回值
private void btnHasParamHasReturn_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Task<int> task1 = new Task<int>(new Func<object, int>((a) =>
{
Console.WriteLine("a={0}", a);
Thread.Sleep(2000);
return 66;
}), "wulaaa");
task1.Start();
Task<int> task2 = new Task<int>(new Func<object, int>((b) =>
{
Console.WriteLine("b={0}", b);
Thread.Sleep(3000);
return 99;
}), "wulbbb");
task2.Start();
int result1 = task1.Result;
int result2 = task2.Result;
Console.WriteLine("result1={0},result2={1}", result1, result2);
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
14、有参数有返回值 不阻塞
private void btnHasParamHasReturnNoBlock_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Task.Run(() =>
{
Task<int> task1 = new Task<int>(new Func<object, int>((a) =>
{
Console.WriteLine("a={0}", a);
Thread.Sleep(2000);
return 66;
}), "wulaaa");
task1.Start();
Task<int> task2 = new Task<int>(new Func<object, int>((b) =>
{
Console.WriteLine("b={0}", b);
Thread.Sleep(3000);
return 99;
}), "wulbbb");
task2.Start();
int result1 = task1.Result;
int result2 = task2.Result;
Console.WriteLine("result1={0},result2={1}", result1, result2);
});
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
五、ThreadPool实现多线程
1、QueueUserWorkItem的用法
无论用户工作项是否超过线程池的最大线程数都不会阻塞主线程 。
private void btnQueueUserWorkItem_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
ThreadPool.SetMinThreads(2, 1);
ThreadPool.SetMaxThreads(4, 2);
ThreadPool.QueueUserWorkItem(new WaitCallback((a) =>
{
Console.WriteLine("WorkItem1-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(2000);
Console.WriteLine("WorkItem1-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}));
ThreadPool.QueueUserWorkItem(new WaitCallback((a) =>
{
Console.WriteLine("WorkItem2-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(3000);
Console.WriteLine("a={0}", a);
Console.WriteLine("WorkItem2-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}),"wulaaa");
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
六、Parallel实现多线程
用户待处理Action无论是否超过最大并行度的数量,都会阻塞主线程。
1、For的用法
private void btnFor_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Console.WriteLine("--------------------");
ParallelOptions options = new ParallelOptions();
//设置最大并行度
options.MaxDegreeOfParallelism = 3;
Parallel.For(1, 6, options, (a, loopState) =>
{
Thread.Sleep(3000);
Console.WriteLine("a={0},{1}", a, DateTime.Now);
});
Console.WriteLine("--------------------");
Parallel.For(1, 6, options, (b, loopState) =>
{
Console.WriteLine("b={0}-Start:{1}", b, DateTime.Now);
//立即停止执行当前循环之外的其他循环
if (b == 1) loopState.Break();
Thread.Sleep(3000);
Console.WriteLine("b={0}-End:{1}", b, DateTime.Now);
});
Console.WriteLine("--------------------");
Parallel.For(1, 6, options, (c, loopState) =>
{
Console.WriteLine("c={0}-Start:{1}", c, DateTime.Now);
//立即停止执行当前循环及其他未执行的循环
if (c == 3) loopState.Stop();
if (loopState.IsStopped) return;
Thread.Sleep(3000);
Console.WriteLine("c={0}-End:{1}", c, DateTime.Now);
});
Console.WriteLine("--------------------");
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
2、Foreach的用法
private void btnForeach_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Console.WriteLine("--------------------");
ParallelOptions options = new ParallelOptions();
//设置最大并行度
options.MaxDegreeOfParallelism = 3;
Parallel.ForEach<int>(new int[] { 1, 2, 3, 4, 5 }, options, (a, loopState) =>
{
Thread.Sleep(3000);
Console.WriteLine("a={0},{1}", a, DateTime.Now);
});
Console.WriteLine("--------------------");
Parallel.ForEach<int>(new int[] { 1, 2, 3, 4, 5 }, options, (b, loopState) =>
{
Console.WriteLine("b={0}-Start:{1}", b, DateTime.Now);
//立即停止执行当前循环之外的其他循环
if (b == 1) loopState.Break();
Thread.Sleep(3000);
Console.WriteLine("b={0}-End:{1}", b, DateTime.Now);
});
Console.WriteLine("--------------------");
Parallel.ForEach<int>(new int[] { 1, 2, 3, 4, 5 }, options, (c, loopState) =>
{
Console.WriteLine("c={0}-Start:{1}", c, DateTime.Now);
//立即停止执行当前循环及其他未执行的循环
if (c == 3) loopState.Stop();
if (loopState.IsStopped) return;
Thread.Sleep(3000);
Console.WriteLine("c={0}-End:{1}", c, DateTime.Now);
});
Console.WriteLine("--------------------");
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
3、Invoke操作
private void btnInvoke_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = 3;
Parallel.Invoke(options,
() =>
{
Console.WriteLine("Sub1-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(1000);
Console.WriteLine("Sub1-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
},
() =>
{
Console.WriteLine("Sub2-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(3000);
Console.WriteLine("Sub2-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
},
() =>
{
Console.WriteLine("Sub3-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(5000);
Console.WriteLine("Sub3-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
},
() =>
{
Console.WriteLine("Sub4-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(1000);
Console.WriteLine("Sub4-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
},
() =>
{
Console.WriteLine("Sub5-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(1000);
Console.WriteLine("Sub5-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
);
Console.WriteLine("--------------------");
Parallel.Invoke(options,
() =>
{
Console.WriteLine("Sub1-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(1000);
Console.WriteLine("Sub1-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
},
() =>
{
Console.WriteLine("Sub2-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(3000);
Console.WriteLine("Sub2-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
);
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
七、async+await实现多线程
private void btnAsync_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Async();
Console.WriteLine("Main-Async()之后【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(8000);
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
private async void Async()
{
Console.WriteLine("Async-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Task task1 = Task.Run(() =>
{
Console.WriteLine("task1-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(3000);
Console.WriteLine("task1-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
Console.WriteLine("await task1之前【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
await task1;
Console.WriteLine("await task1之后【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Task task2 = Task.Run(() =>
{
Console.WriteLine("task2-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
Thread.Sleep(3000);
Console.WriteLine("task2-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
});
await task2;
Console.WriteLine("Async-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
八、取消多线程的执行
1、CancellationTokenSource的用法1
Task+CancellationTokenSource共有三种写法:
CancellationTokenSource cts = new CancellationTokenSource();
taskFactory.StartNew(() => { }, cts.Token);
Task task3 = new Task(() => { }, cts.Token);
Task.Run(() => { }, cts.Token);
private void btnInnerCancel_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
CancellationTokenSource cts = new CancellationTokenSource();
Task task1 = new Task(() => {
Thread.Sleep(2000);
if (cts.IsCancellationRequested)
{
Console.WriteLine("task1:cts已经被取消了");
}
else
{
cts.Cancel();
Console.WriteLine("task1:取消cts");
}
}, cts.Token);
Task task2 = new Task(() => {
Thread.Sleep(3000);
if (cts.IsCancellationRequested)
{
Console.WriteLine("task2:cts已经被取消了");
}
else
{
cts.Cancel();
Console.WriteLine("task2:取消cts");
}
}, cts.Token);
task1.Start();
task2.Start();
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
2、CancellationTokenSource的用法2
private void btnExternalCancel_Click(object sender, EventArgs e)
{
Console.WriteLine("Main-Start【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
CancellationTokenSource cts = new CancellationTokenSource();
TaskFactory taskFactory = new TaskFactory();
cts.Cancel();
Task task1 = taskFactory.StartNew(() => {
Thread.Sleep(2000);
if (cts.IsCancellationRequested)
{
Console.WriteLine("task1:cts已经被取消了");
}
else
{
cts.Cancel();
Console.WriteLine("task1:取消cts");
}
}, cts.Token);
Task task2 = taskFactory.StartNew(() => {
Thread.Sleep(3000);
if (cts.IsCancellationRequested)
{
Console.WriteLine("task2:cts已经被取消了");
}
else
{
cts.Cancel();
Console.WriteLine("task2:取消cts");
}
}, cts.Token);
Console.WriteLine("Main-End【ThreadId=" + Thread.CurrentThread.ManagedThreadId + "】:" + DateTime.Now);
}
3、ManualResetEvent的用法
//参数值为false线程默认会阻塞
private ManualResetEvent mre = new ManualResetEvent(false);
private void btnManuResetEvent_Click(object sender, EventArgs e)
{
Thread thread = new Thread(Run);
thread.Start();
}
private void Run()
{
while (true)
{
this.mre.WaitOne();
Thread.Sleep(1000);
Console.WriteLine("ThreadId=" + Thread.CurrentThread.ManagedThreadId + ":" + DateTime.Now);
}
}
private void btnStart_Click(object sender, EventArgs e)
{
//放开线程
this.mre.Set();
}
private void btnStop_Click(object sender, EventArgs e)
{
//阻塞线程
this.mre.Reset();
}