浅谈.Net的异步
一,异步编程的步骤
1,建立与被调用方法相同签名的委托
假设被调用的方法为public void TestMethod(string p)
Public delegate void AsyncDelegate(string p);
2,把被调用的方法注册到委托实例
AsyncDelegate ad=new AsyncDelegate(TestMethod);
3,以begininvoke开始调用异步方法
IAsyncResult ar =Ad.BeginInvoke(string p,null,null)
4,继续做一些不需要异步调用结果的操作
//做一些其它操作
5,在需要异步调用方法结果的时候,察看异步调用方法执行的结果,并同步等待异步调用完成。
while(ar.IsCompleted == false)
{
Thread.Sleep(10);
}
Ad.EndBeginInvoke();
//继续操作
二, 实例
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace TestAsyn
{
//声明与被调用方法相同的委托
public delegate void AddHandle();
/// <summary>
/// Form1 的摘要说明。
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
public AddHandle add;
private System.Windows.Forms.Button button3;
private System.Windows.Forms.Button button4;
private IAsyncResult ar;
private System.Windows.Forms.Label label2;
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null;
public Form1()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();
//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.button3 = new System.Windows.Forms.Button();
this.button4 = new System.Windows.Forms.Button();
this.label2 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// label1
//
this.label1.Location = new System.Drawing.Point(152, 32);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(152, 23);
this.label1.TabIndex = 0;
//
// button1
//
this.button1.Location = new System.Drawing.Point(88, 88);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(336, 23);
this.button1.TabIndex = 1;
this.button1.Text = "同步操作(程序会在未执行完失去相应)";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// button2
//
this.button2.Location = new System.Drawing.Point(88, 144);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(328, 23);
this.button2.TabIndex = 2;
this.button2.Text = "异步执行(但还是没用相应)";
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// button3
//
this.button3.Location = new System.Drawing.Point(8, 208);
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(312, 23);
this.button3.TabIndex = 3;
this.button3.Text = "异步执行(可以做一些不需要异步调用结果的操作)";
this.button3.Click += new System.EventHandler(this.button3_Click);
//
// button4
//
this.button4.Location = new System.Drawing.Point(344, 208);
this.button4.Name = "button4";
this.button4.Size = new System.Drawing.Size(312, 23);
this.button4.TabIndex = 4;
this.button4.Text = "异步执行(需要做一些需要异步调用结果的操作)";
this.button4.Click += new System.EventHandler(this.button4_Click);
//
// label2
//
this.label2.Location = new System.Drawing.Point(96, 272);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(488, 23);
this.label2.TabIndex = 5;
this.label2.Text = "提示信息:";
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(680, 413);
this.Controls.Add(this.label2);
this.Controls.Add(this.button4);
this.Controls.Add(this.button3);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Controls.Add(this.label1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void
{
Application.Run(new Form1());
}
private void AddMethod()
{
for(int i=0;i<10000;i++)
{
this.label1.Text=i.ToString();
}
}
private void button1_Click(object sender, System.EventArgs e)
{
this.AddMethod();
}
private void button2_Click(object sender, System.EventArgs e)
{
IAsyncResult ar=this.add.BeginInvoke(null,null);
this.add.EndInvoke(ar);
}
private void Form1_Load(object sender, System.EventArgs e)
{
//把被调用的方法注册到委托上
this.add=new AddHandle(this.AddMethod);
}
private void button3_Click(object sender, System.EventArgs e)
{
this.ar=this.add.BeginInvoke(null,null);
}
private void button4_Click(object sender, System.EventArgs e)
{
if(!this.ar.IsCompleted)
{
this.label2.Text="提示信息:异步方法还没有执行完,请等待。";
}
else
{
this.add.EndInvoke(this.ar);
MessageBox.Show("异步操作完成,弹出一对话框");
}
// this.add.EndInvoke(this.ar);
// MessageBox.Show("异步操作完成,弹出一对话框");
}
}
}
三,在异步调用中使用IAsyncResult(表示异步操作的状态)和AsyncCallback(异步调用完成时执行回调方法)
1,建立与被调用方法相同签名的委托
假设被调用的方法为public void TestMethod(string p)
Public delegate void AsyncDelegate(string p);
2,把被调用的方法注册到委托实例
AsyncDelegate ad=new AsyncDelegate(TestMethod);
3,定义异步调用完成时执行的回调方法
Public void CallbackMethod(IAsyncResult ar)
4,以begininvoke开始调用异步方法
IAsyncResult ar =Ad.BeginInvoke(string p,new AsyncCallback(CallbackMethod),null)
5,继续做一些不需要异步调用结果的操作
//做一些其它操作
四,实例
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace TestAsyn
{
//声明与被调用方法相同的委托
public delegate void AddHandle();
/// <summary>
/// Form1 的摘要说明。
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
public AddHandle add;
private System.Windows.Forms.Button button3;
private System.Windows.Forms.Button button4;
private IAsyncResult ar;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button button5;
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null;
public string Labeltext
{
get
{
return this.label1.Text;
}
}
public Form1()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();
//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.button3 = new System.Windows.Forms.Button();
this.button4 = new System.Windows.Forms.Button();
this.label2 = new System.Windows.Forms.Label();
this.button5 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// label1
//
this.label1.Location = new System.Drawing.Point(152, 32);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(152, 23);
this.label1.TabIndex = 0;
//
// button1
//
this.button1.Location = new System.Drawing.Point(88, 88);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(336, 23);
this.button1.TabIndex = 1;
this.button1.Text = "同步操作(程序会在未执行完失去相应)";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// button2
//
this.button2.Location = new System.Drawing.Point(88, 144);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(328, 23);
this.button2.TabIndex = 2;
this.button2.Text = "异步执行(但还是没用相应)";
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// button3
//
this.button3.Location = new System.Drawing.Point(8, 208);
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(312, 23);
this.button3.TabIndex = 3;
this.button3.Text = "异步执行(可以做一些不需要异步调用结果的操作)";
this.button3.Click += new System.EventHandler(this.button3_Click);
//
// button4
//
this.button4.Location = new System.Drawing.Point(344, 208);
this.button4.Name = "button4";
this.button4.Size = new System.Drawing.Size(312, 23);
this.button4.TabIndex = 4;
this.button4.Text = "异步执行(需要做一些需要异步调用结果的操作)";
this.button4.Click += new System.EventHandler(this.button4_Click);
//
// label2
//
this.label2.Location = new System.Drawing.Point(96, 272);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(488, 23);
this.label2.TabIndex = 5;
this.label2.Text = "提示信息:";
//
// button5
//
this.button5.Location = new System.Drawing.Point(136, 328);
this.button5.Name = "button5";
this.button5.Size = new System.Drawing.Size(304, 23);
this.button5.TabIndex = 6;
this.button5.Text = "异步执行(执行完成自动调用回调方法)";
this.button5.Click += new System.EventHandler(this.button5_Click);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(680, 413);
this.Controls.Add(this.button5);
this.Controls.Add(this.label2);
this.Controls.Add(this.button4);
this.Controls.Add(this.button3);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Controls.Add(this.label1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void AddMethod()
{
for(int i=0;i<10000;i++)
{
this.label1.Text=i.ToString();
}
}
private void button1_Click(object sender, System.EventArgs e)
{
this.AddMethod();
}
private void button2_Click(object sender, System.EventArgs e)
{
IAsyncResult ar=this.add.BeginInvoke(null,null);
this.add.EndInvoke(ar);
}
private void Form1_Load(object sender, System.EventArgs e)
{
//把被调用的方法注册到委托上
this.add=new AddHandle(this.AddMethod);
}
private void button3_Click(object sender, System.EventArgs e)
{
this.ar=this.add.BeginInvoke(null,null);
}
public void CallBackMethod(IAsyncResult ar)
{
Form1 f = (Form1) ar.AsyncState;
MessageBox.Show("执行完成,窗体上label1的text的值为"+f.Labeltext);
}
private void button4_Click(object sender, System.EventArgs e)
{
if(!this.ar.IsCompleted)
{
this.label2.Text="提示信息:异步方法还没有执行完,请等待。";
}
else
{
this.add.EndInvoke(this.ar);
MessageBox.Show("异步操作完成,弹出一对话框");
}
// this.add.EndInvoke(this.ar);
// MessageBox.Show("异步操作完成,弹出一对话框");
}
private void button5_Click(object sender, System.EventArgs e)
{
this.ar=this.add.BeginInvoke(new AsyncCallback(this.CallBackMethod),this);
}
}
}
五,总结“异步方法签名”
方法签名是参数类型在一个方法中的顺序。BeginInvoke 异步方法签名的规则是:
- 包括所有 IN 参数。
- 包括所有 OUT 参数。
- 包括所有 IN/OUT 参数。
- 包括所有 ByRef 参数。
- 将 AsyncCallback 和 AsyncState(可通过 IAsyncResult 接口的 AsyncState 属性获得)作为最后两个参数。
- 返回 IAsyncResult。
EndInvoke 异步方法签名的规则是:
- 包括所有 IN/OUT 参数。
- 包括所有 OUT 参数。
- 包括所有 ByRef 参数。
- 将 IAsyncResult 作为最后一个参数。
- 从原始方法签名返回原始返回类型。
结果对象 (IAsyncResult) 是从开始操作返回的,并且可用于获取有关异步开始操作是否已完成的状态。结果对象被传递到结束操作,该操作返回调用的最终返回值。在开始操作中可以提供可选的回调。如果提供回调,在调用结束后,将调用该回调;并且回调中的代码可以调用结束操作。