Bootstrap

C#异步多线程总结(delegate、Thread、Task、ThreadPool、Parallel、async、cancel)

同步与异步多线程的区别:

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();
}

 

;