阻塞式编程:我们一边编写的代码都是同步代码,也就是从上到下按照顺序执行。
例如
public delegate void DoWorkHandler();
class Program
{
static void Main(string[] args)
{
Console.WriteLine("开始烧水了");
// 一直等到水烧开
DoWorkHandler handler = (() =>
{
Thread.Sleep(2000);
Console.WriteLine("水烧好了");
});
handler.Invoke();
// 在水未烧开之前一直会有阻塞
Console.WriteLine("扫一下地吧");
}
}
或者这样形式
public delegate int DoWorkHandler(int ms);
class Program
{
static void Main(string[] args)
{
Console.WriteLine("程序开始");
// 一直等到水烧开
DoWorkHandler handler = BoilWaterHandler;
IAsyncResult asyncResult = handler.BeginInvoke(2000, null, null);
//EndInvoke方法将被阻塞2秒。一直等待委托完成其任务为止
int result = handler.EndInvoke(asyncResult);
Console.WriteLine(result);
Console.WriteLine("扫一下地吧");
Console.ReadKey();
}
static int BoilWaterHandler(int ms)
{
Console.WriteLine("开始烧水");
Thread.Sleep(ms);
Console.WriteLine("烧水完成");
return ++ms;
}
}
都是要阻塞2秒。怎样防止程序被阻塞,让CPU继续执行其他任务呢?
为了解决以上问题,我们需要使用异步的方式编程,原理其实就是遇到耗时较多的任务时,操作系统实现了时间片轮转调度算法,切换到另一个线程。
方案1、用委托(Delegate)的BeginInvoke和EndInvoke方法操作线程,使用IAsyncResult.IsCompleted属性来判断异步调用是否完成。在C#中,Delegate类包含Invoke和BeginInvoke两个方法,其中Invoke是同步的,而BeginInvoke则是异步的
public delegate void DoWorkHandler();
class Program
{
static void Main(string[] args)
{
Console.WriteLine("开始烧水了");
// 一直等到水烧开
DoWorkHandler handler = (() =>
{
Thread.Sleep(5000);
Console.WriteLine("水烧好了");
});
// 这里不会有阻塞,我们可以做一些其他事情
IAsyncResult asyncResult = handler.BeginInvoke(null, null);
while (!asyncResult.IsCompleted)
{
Console.WriteLine("水还没烧好,先干点其的他事情吧");
Thread.Sleep(1000);
}
Console.WriteLine("扫一下地吧");
Console.ReadKey();
}
}
方案2、使用回调方式返回结果
第一种写法
public delegate void DoWorkHandler();
class Program
{
static void Main(string[] args)
{
Console.WriteLine("开始烧水了");
// 一直等到水烧开
DoWorkHandler handler = (() =>
{
Thread.Sleep(5000);
Console.WriteLine("水烧好了");
});
// 异步回调
IAsyncResult asyncResult = handler.BeginInvoke(new AsyncCallback(CallBack), null);
while (!asyncResult.IsCompleted)
{
Console.WriteLine("水还没烧好,先干点其的他事情吧");
Thread.Sleep(1000);
}
Console.WriteLine("扫一下地吧");
Console.ReadKey();
}
static void CallBack(IAsyncResult result)
{
DoWorkHandler handler = (result as AsyncResult).AsyncDelegate as DoWorkHandler;
handler.EndInvoke(result);
}
![](https://img-blog.csdnimg.cn/2020010621332080.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NpbmF0XzMxNjA4NjQx,size_16,color_FFFFFF,t_70)
第二种写法
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace 异步编程测试
{
public delegate int DoWorkHandler(int ms);
class Program
{
static void Main(string[] args)
{
Console.WriteLine("开始烧水了");
// 一直等到水烧开
DoWorkHandler handler = DoHeatWater;
handler.BeginInvoke(3000, CallBack, handler);
Console.WriteLine("扫一下地吧");
Console.ReadKey();
}
static int DoHeatWater(int ms)
{
Thread.Sleep(ms);
Console.WriteLine("水烧好了");
return ++ms;
}
static void CallBack(IAsyncResult result)
{
if (result == null)
{
throw new ArgumentNullException("result");
}
DoWorkHandler handler = result.AsyncState as DoWorkHandler;
Trace.Assert(handler != null, "invalid objevt type");
int data = handler.EndInvoke(result);
Console.WriteLine(data);
}
}
}
![](https://img-blog.csdnimg.cn/20200106213430996.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NpbmF0XzMxNjA4NjQx,size_16,color_FFFFFF,t_70)
参考:
https://blog.csdn.net/qq_34057374/article/details/76460578
https://blog.csdn.net/HerryDong/article/details/82825548