异步分为以下大概4个步骤:
①声明一个委托类型
②创建委托类型的变量
③为委托绑定一个方法(返回值和参数列表与委托相同)
④异步调用委托
示例一:自定义委托类型
//【1】声明一个委托
public delegate int MyCalculator(int num,int ms);
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//【3】使用lamda表达式传参并交代执行方法
this.objMyCal = (num,ms) =>
{
Thread.Sleep(ms);
return num * num;
};
}
//【2】创建委托变量
MyCalculator objMyCal = null;
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
//【4】开始异步执行,封装回调函数:BeginInvoke(参数,回调函数,回调函数多需的对象/参数)
objMyCal.BeginInvoke(10 * i, 1000 * i, MyCallBack, i);
}
}
private void MyCallBack(IAsyncResult result)
{
int res = objMyCal.EndInvoke(result);
Console.WriteLine("第{1}个计算结果为:{0}", res, result.AsyncState.ToString());
}
}
示例二:使用Func<>标准委托、用于需要返回值的场景
//【1】声明一个名为Operation的委托,并交代执行方法
//int:传入参数类型 string:返回值类型
public Func<int, string> Operation = (num) =>
{
Thread.Sleep(num * 1000);
return num.ToString();
};
private void button1_Click(object sender, EventArgs e)
{
//【2】异步调用
IAsyncResult str = Operation.BeginInvoke(2, CallBack, "发送给回调函数的参数");
}
//【3】回调函数:这里可以做一些耗时的任务,等待委托的执行结果
public void CallBack(IAsyncResult result)
{
string res = Operation.EndInvoke(result); //返回结果(结果类型,与委托返回值类型一致)
var v = result.AsyncState; //获取传递给回调函数的参数【打印:"发送给回调函数的参数"】
}
注意点:
- BeginInvoke(参数列表,BallBack(),传递给回调函数的参数,回调函数中接收类型为IAsyncResult类型,使用AsyncState属性可以获取传递结果)
- EndInvoke()处于回调函数的时候,不卡主界面,否则卡顿主界面(可以返回结果,也可以不返回,根据委托)。
- 回调函数中接收一个IAsyncResult接口,通过获取AsyncState属性得到结果。
示例三:使用Action<>标准委托,用于不需要返回值的场景
同步方式,卡界面,且线程一直都是运行在主线程之上
异步方式,不卡界面,每次运行的线程都是有CPU随机调取的
//声明一个带string类型参数的委托
public Action<string> DelMethod;
public Form1()
{
InitializeComponent();
DelMethod = PrintStr; //指向PrintStr函数
}
//同步线程执行
private void button1_Click(object sender, EventArgs e)
{
//卡窗体(卡主线程)
Console.WriteLine("Main Thd:" + Thread.CurrentThread.ManagedThreadId);
this.DelMethod.Invoke("这是一个同步输出结果。。。");
}
public void PrintStr(string str)
{
for (int i = 0; i < 5; i++)
{
Thread.Sleep(500);
Console.WriteLine(str + "\t" + "Seq:" + i + "\t" + "Thd:" + Thread.CurrentThread.ManagedThreadId);
}
}
//异步线程执行
private void button2_Click(object sender, EventArgs e)
{
//不卡主线程
IAsyncResult iar = this.DelMethod.BeginInvoke("这是一个异步输出结果。。。", new AsyncCallback((s) =>
{
Console.WriteLine(s.AsyncState.ToString() + "\t" + "Thd:" + Thread.CurrentThread.ManagedThreadId);
}), "异步表演结束");
//主线程上执行的代码,用于测试执行顺序
Console.WriteLine("\r\n" + "运行在主线程上的程序" + "\t" + Thread.CurrentThread.ManagedThreadId);
}
如有错误,欢迎及时批评指正,谢谢。。。