基础整理 多线程和异步编程
假设完成一个操作需要经历1、2、3、4、5五个步骤,通常我们编程的时候按照1、2、3、4、5顺序执行就可以了,但是2、3、4这几个步骤耗费时间比较长,2、3、4同时做对程序也没有影响,这个时候多线程就有了用武之地,我们可以在执行完1后,分别开启不同的线程来执行2、3、4,待它们执行完成后再执行5,这样就可以大大的节约程序的执行时间,通过Thread我们可以很容易创建线程:
static void Main(string[] args)
{
Console.WriteLine("开始执行");
new Thread(Action).Start(); //带参
new Thread(ActionWithParams).Start("张三"); //不带参
Console.WriteLine("执行完毕");
Console.ReadLine();
}
public static void Action()
{
Console.WriteLine("你好");
}
public static void ActionWithParams(object args)
{
Console.WriteLine("你好,{0}", args.ToString());
}
但是线程的销毁和创建比较耗费系统资源,出于性能考虑,C#引入了线程池概念,由线程池(ThreadPool)来负责创建和销毁线程,如:
static void Main(string[] args)
{
Console.WriteLine("开始执行");
ThreadPool.QueueUserWorkItem(ActionWithParams, "李四");
Console.WriteLine("执行完毕");
Console.ReadLine();
}
public static void Action()
{
Console.WriteLine("你好");
}
public static void ActionWithParams(object args)
{
Console.WriteLine("你好,{0}", args.ToString());
}
通过多线程我们可以避免线程阻塞,我们还可以通过异步的方式来达到目的,大多数时候我们容易把多线程和异步操作搞混,但其实他们还是由一定区别的:
- 多线程是进程中并行运行的代码段,需要CPU消耗资源来运行和调度
- 异步操作是使用回调的方式进行处理,没有额外的CPU消耗
我们可以使用BeginInvoke和EndInvoke来进行异步操作,BeginInvoke方法可以使用线程异步的执行委托的方法,然后通过EndInvoke获取方法的返回值,获者确定方法已经正确执行完毕。
private delegate bool ActionDelegate(string name);
static void Main(string[] args)
{
Console.WriteLine("开始执行");
ActionDelegate ad = ActionWithParams;
var ar = ad.BeginInvoke("李四", null, null); //创建一个后台线程
Thread.Sleep(1000);
Console.WriteLine("Blablabla");
Console.WriteLine(ar.IsCompleted); //该属性可以判断异步调用是否完成
//ar.AsyncWaitHandle.WaitOne(3000, false); //当然我们也可以通过WatiOne来判断
var re = ad.EndInvoke(ar);
Console.WriteLine(re);
Console.WriteLine("执行完毕");
Console.ReadLine();
}
public static bool ActionWithParams(string name)
{
Console.WriteLine("你好,{0}", name);
Thread.Sleep(3000);
return true;
}
当然我们也可以使用Task来实现:
static void Main(string[] args)
{
Console.WriteLine("开始执行");
Task<bool> task = new Task<bool>(ActionWithParams, "张三");
task.Start();
task.Wait();
task.ContinueWith<bool>(ActionWithParmasNext);
Console.WriteLine(task.Result);
Console.WriteLine("执行完毕");
Console.ReadLine();
}
public static bool ActionWithParams(object args)
{
Console.WriteLine("你好,{0}", args.ToString());
return true;
}
public static bool ActionWithParmasNext(Task<bool> next)
{
Console.WriteLine("第二步操作");
return true;
}
但是这样声明还是觉得麻烦,于是便有了async&wait,如下:
private delegate bool ActionDelegate(string name);
static void Main(string[] args)
{
Console.WriteLine("开始执行");
var hello = SayHello(); //标记了async&await后也可以达到异步执行的效果
Console.WriteLine("执行完毕");
Console.ReadLine();
}
static async Task<string> SayHello()
{
await Task.Delay(2000); //延迟执行
Console.WriteLine("Hello");
return "你好";
}