异步编程:利用委托实现的.NET历史上第一个异步编程模型
同步:前面的做完了,才轮到我来做;
异步:同一时间各做各的,互不干扰;相当于我们生活中常说的"同步"
方法的同步调用与异步调用:
- 程序运行起来就会创建一个进程;
- 一个进程中可以有多个线程;
- 同步调用是指在一个线程中,顺次执行;
- 异步调用需要依靠多线程;
- 同步、串行、单线程 指的是一个意思;
- 异步、并行、多线程 指的是一个意思;
使用方法名,直接同步调用
class Program
{
static void Main(string[] args)
{
//方法的直接调用就是一种同步执行--执行完一个再执行下一个
Dog dog1 = new Dog() { DogName = "嘟嘟", ConsoleColor = ConsoleColor.Red };
dog1.WangWang();
Console.WriteLine(dog1.DogName+"汪汪叫完毕");
Thread.Sleep(TimeSpan.FromSeconds(0.5));
Dog dog2 = new Dog() { DogName = "壮壮", ConsoleColor = ConsoleColor.Green };
dog2.WangWang();
Console.WriteLine(dog2.DogName + "汪汪叫完毕");
Thread.Sleep(TimeSpan.FromSeconds(0.5));
Dog dog3 = new Dog() { DogName = "小强", ConsoleColor = ConsoleColor.Yellow };
dog3.WangWang();
Console.WriteLine(dog3.DogName + "汪汪叫完毕");
Thread.Sleep(TimeSpan.FromSeconds(0.5));
for (int i = 0; i < 6; i++)
{
Console.ForegroundColor = ConsoleColor.Magenta;
Console.WriteLine("Main方法中的操作{0}",i);
Thread.Sleep(TimeSpan.FromSeconds(0.5));
}
Console.ReadKey();
}
static void PrintRed()
{
for (int i = 0; i < 5; i++)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(i);
Thread.Sleep(TimeSpan.FromSeconds(1));
}
}
}
class Dog
{
public string DogName { get; set; }
public ConsoleColor ConsoleColor { get; set; }
public void WangWang()
{
for (int i = 1; i < 4; i++)
{
Console.ForegroundColor = this.ConsoleColor;
Console.WriteLine($"狗狗--{DogName},叫了第{i}声");
Thread.Sleep(TimeSpan.FromSeconds(0.5));
}
}
}
使用委托,间接同步调用
//只改动Main方法中的部分代码,其余代码与上面的例子中代码保持一致
static void Main(string[] args)
{
//将WangWang方法交给委托,然后进行间接同步调用
Dog dog1 = new Dog() { DogName = "嘟嘟", ConsoleColor = ConsoleColor.Red };
Dog dog2 = new Dog() { DogName = "壮壮", ConsoleColor = ConsoleColor.Green };
Dog dog3 = new Dog() { DogName = "小强", ConsoleColor = ConsoleColor.Yellow };
Action action1 = new Action(dog1.WangWang);
Action action2 = new Action(dog2.WangWang);
Action action3 = new Action(dog3.WangWang);
action1.Invoke();
Console.WriteLine($"{dog1.DogName}叫完了");
action2.Invoke();
Console.WriteLine($"{dog2.DogName}叫完了");
action3.Invoke();
Console.WriteLine($"{dog3.DogName}叫完了");
for (int i = 0; i < 6; i++)
{
Console.ForegroundColor = ConsoleColor.Magenta;
Console.WriteLine("Main方法中的操作{0}",i);
Thread.Sleep(TimeSpan.FromSeconds(0.5));
}
Console.ReadKey();
}
使用Thread/Task等,显示异步(多线程)调用
static void Main(string[] args)
{
//将WangWang方法交给一个子线程 线程启动后 便可异步执行WangWang方法
Dog dog1 = new Dog() { DogName = "嘟嘟", ConsoleColor = ConsoleColor.Red };
Dog dog2 = new Dog() { DogName = "壮壮", ConsoleColor = ConsoleColor.Green };
Dog dog3 = new Dog() { DogName = "小强", ConsoleColor = ConsoleColor.Yellow };
Thread thread1 = new Thread(dog1.WangWang);
Thread thread2 = new Thread(dog2.WangWang);
Thread thread3 = new Thread(dog3.WangWang);
thread1.Start();
thread2.Start();
thread3.Start();
for (int i = 0; i < 6; i++)
{
Console.ForegroundColor = ConsoleColor.Magenta;
Console.WriteLine("Main方法中的操作{0}",i);
Thread.Sleep(TimeSpan.FromSeconds(0.5));
}
Console.ReadKey();
}
使用委托,隐式异步(多线程)调用--BeginInvoke
static void Main(string[] args)
{
//将WangWang方法交给委托,通过委托的BeginInvoke方法,可以隐式地实现异步调用
Dog dog1 = new Dog() { DogName = "嘟嘟", ConsoleColor = ConsoleColor.Red };
Dog dog2 = new Dog() { DogName = "壮壮", ConsoleColor = ConsoleColor.Green };
Dog dog3 = new Dog() { DogName = "小强", ConsoleColor = ConsoleColor.Yellow };
Action action1 = new Action(dog1.WangWang);
Action action2 = new Action(dog2.WangWang);
Action action3 = new Action(dog3.WangWang);
action1.BeginInvoke(null,null);
action2.BeginInvoke(item => { Console.WriteLine($"{(item.AsyncState as Dog).DogName}叫完了"); },dog2);
action3.BeginInvoke(xx => { Console.WriteLine($"{dog3.DogName}叫完了"); },null);
for (int i = 0; i < 6; i++)
{
Console.ForegroundColor = ConsoleColor.Magenta;
Console.WriteLine("Main方法中的操作{0}",i);
Thread.Sleep(TimeSpan.FromSeconds(0.5));
}
Console.ReadKey();
}
- 可以看出:BeginInvoke方法隐式地将方法放到多线程中去执行,BeginInvoke方法调用后立刻返回,接着执行Main方法中的下一行代码。BeginInvoke方法还接受两个参数:第一个是委托类型的回调--当多线程的方法执行结束后执行回调方法;第二个参数--异步调用的方法结束后,该参数会作为调用结果IAsyncResult实例的AsyncState属性值
- 还可以看出:使用Thread启动多线程后,并不能得知什么时候异步调用的方法执行完毕;我们就不能在异步方法执行完毕后,进行一些相应的后续操作。但是,BeginInvoke就可以
以上便是对使用委托进行方法的异步调用的总结,记录下来以便以后查阅。