C# 多线程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# 多线程相关的知识,希望对你有一定的参考价值。

自FrameWork 2.0后 , 多线程在Thread后又进行了很好的封装,管理多线程变得更加的简单。现对C#多线程的知识点进行管理归纳。

Thread类的使用:(但是参数只能是一个Object类)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace SampleThread
{
    class Program
    {
        static void Main(string[] args)
        {
            Thread noParamThread = new Thread(new ThreadStart(NoParamMethod));
            Thread hasParamThread = new Thread(new ParameterizedThreadStart(HasParamMethod));//带参的函数
            noParamThread.Start();
            hasParamThread.Start("Ainy");//需要传参
            Console.ReadKey();
        }
        private static void NoParamMethod()
        {
            Console.WriteLine("不带参数的函数");
        }
        private static void HasParamMethod(Object ob)
        {
            String str = ob as string;
            Console.WriteLine("带参数的函数 , 参数 : {0}" , str);
        }
    }
}

ThreadPool(线程池)类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ThreadPoolTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //ThreadPool.QueueUserWorkItem(HasParamMethod, "Ainy");
            ThreadPool.QueueUserWorkItem(HasParamMethod);
            Console.ReadKey();
        }
        private static void HasParamMethod(Object ob)
       {
            String str = ob as string;
            Console.WriteLine("带参数的函数 , 参数为 : {0}",str);
        }
    }
}


因为QueueUserWorkItem的方法重载有2个:

public static bool QueueUserWorkItem(WaitCallback callBack);
public static bool QueueUserWorkItem(WaitCallback callBack, object state);

而WaitCallBack是一个Delegate:

public delegate void WaitCallback(object state);

所以,QueueUserWorkItem的参数方法,必须带一个Object的参数,可用Null判断参数Object是否有效。


Task(任务)类

Task<TResult> :  TResult->返回类型。那么Task就是没有Return了。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TaskTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Task<string> helloTask = new Task<string>(n=>Hello(n as string), "Ainy");
            helloTask.Start();
            Task<string> waitHello = helloTask.ContinueWith<string>(hello => { return hello.Result + "  Good"; });
            Task m = waitHello.ContinueWith(wait => Console.WriteLine(wait.Result));
            Console.ReadKey();
        }
        private static string Hello(string name)
        {
            return "Hello , " + name;
        }
    }
}

关于 ContinueWith  : Task<string> waitHello = helloTask.ContinueWith<string>(hello => { return hello.Result + "  Good"; })

当helloTask执行完毕后 , 立马执行waitHello


TaskFactory(任务工厂)类

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TaskFactoryTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            List<Task> tasks = new List<Task>();
            TaskFactory factory = new TaskFactory();
            tasks.Add(factory.StartNew(() => Console.WriteLine("不带参数的!")));
            tasks.Add(factory.StartNew(() => Console.WriteLine("不带参数的!1")));
            tasks.Add(factory.StartNew(() => Console.WriteLine("不带参数的!2")));
            //tasks.Add(new Task(() => Console.WriteLine("XXXXXXXXXXXX")));//不要用这种方法添加Task
            
            //用以下方式添加Task , 关键在于一个Start开启方法
            Task newTask = new Task(() => Console.WriteLine("XXXXXXXXXXXX"));
            tasks.Add(newTask);
            newTask.Start();
            Task s = factory.ContinueWhenAny(tasks.ToArray(), t => Console.WriteLine("有一个任务已经完成!"));
            Task a = factory.ContinueWhenAll(tasks.ToArray(), t => Console.WriteLine("所有的任务都执行完毕!"));
            tasks.Add(a);
            Task.WaitAll(tasks.ToArray());
            sw.Stop();
            Console.WriteLine("总共耗时 {0}", sw.ElapsedMilliseconds);
            Console.ReadKey();
        }
    }
}

当然有TaskFactory<TResult> 意思是可带返回值的任务


async/await 关键字的使用

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AwaitTest
{
    class Program
    {
        static void Main(string[] args)
        {

            NoReturnOne();
            Task<Int32> taskReturnInt = HasReturn(1, 3);
            Console.WriteLine("Important , 我在执行");
            Console.WriteLine("返回的结果为 : {0}", taskReturnInt.Result);//taskReturnInt.Result 阻塞主线程,直到拿到结果
            Console.WriteLine("执行结束");
            Console.ReadKey();
        }
        /// <summary>
        /// 没有返回值的async async void == async Task
        /// </summary>
        private static async void NoReturnOne()
        {
            Console.WriteLine("No.1 : 执行没有返回值的函数");
            await Task.Run(() => {
                Console.WriteLine(" No.1 : 开始执行异步子线程");
                Thread.Sleep(1000);
                Console.WriteLine("No.1 : 结束异步子线程");
            });
            Console.WriteLine("No.1 结束");
        }
        /// <summary>
        /// 没有返回值的async async Task == async void
        /// </summary>
        /// <returns></returns>
        private static async Task NoReturnTwo()
        {
            Console.WriteLine("No.2 : 执行没有返回值的函数");
            await Task.Run(() =>
            {
                Console.WriteLine(" No.2 : 开始执行异步子线程");
                Thread.Sleep(1000);
                Console.WriteLine("No.2 : 结束异步子线程");
            });
            Console.WriteLine("No.2 结束");
        }
        /// <summary>
        /// 有返回值的
        /// </summary>
        /// <returns>int32</returns>
        private static async Task<Int32> HasReturn(Int32 a , Int32 b )
        {
            Console.WriteLine("No.3 : 执行有返回值的函数");
            Int32 bc = 0;
            await Task.Run(() => {
                bc = a + b;
                Thread.Sleep(1000);
            });
            return bc;
        }
    }
}

执行结果为:

技术分享

可以看出 ,taskReturnInt.Result 会阻塞主线程 ,直到拿到结果。当然 , 如果去点await也行,但是就变成同步的了。

本文出自 “Better_Power_Wisdom” 博客,请务必保留此出处http://aonaufly.blog.51cto.com/3554853/1862145

以上是关于C# 多线程的主要内容,如果未能解决你的问题,请参考以下文章

C# Thread开启线程的几种方式

多个用户访问同一段代码

C#多线程编程

线程学习知识点总结

C#多线程之旅

干货分享:详解线程的开始和创建