一个编译器所支持的异步委托的例子

原创 2002年11月29日 16:37:00
刚写的例子所以发发。。
http://www.lostinet.com/temp/asyncExample.txt
得到代码。
http://www.lostinet.com/temp/asyncExample.exe
运行程序
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Threading;

namespace AsyncExample
{
	/// <summary>
	/// Form1 的摘要说明。
	/// </summary>
	public class Form1 : System.Windows.Forms.Form
	{
		private System.Windows.Forms.GroupBox groupBox1;
		private System.Windows.Forms.TextBox textBox1;
		private System.Windows.Forms.TextBox textBox2;
		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.Label label2;
		private System.Windows.Forms.Button button1;
		private System.Windows.Forms.Button button2;
		private System.ComponentModel.IContainer components;
		private System.Windows.Forms.Button button3;

		private Thread theThread;

		public Form1()
		{
			//
			// Windows 窗体设计器支持所必需的
			//
			InitializeComponent();

			//
			// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
			//

			//把当前线程记录起来,以后比较一下就知道一个函数是否在其他线程中执行了。
			theThread=Thread.CurrentThread;
		}

		/// <summary>
		/// 清理所有正在使用的资源。
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// 设计器支持所需的方法 - 不要使用代码编辑器修改
		/// 此方法的内容。
		/// </summary>
		private void InitializeComponent()
		{
			this.groupBox1 = new System.Windows.Forms.GroupBox();
			this.textBox1 = new System.Windows.Forms.TextBox();
			this.textBox2 = new System.Windows.Forms.TextBox();
			this.label1 = new System.Windows.Forms.Label();
			this.label2 = 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.groupBox1.SuspendLayout();
			this.SuspendLayout();
			// 
			// groupBox1
			// 
			this.groupBox1.Controls.AddRange(new System.Windows.Forms.Control[] {
																					this.button3,
																					this.button2,
																					this.label2,
																					this.label1,
																					this.textBox2,
																					this.textBox1,
																					this.button1});
			this.groupBox1.Name = "groupBox1";
			this.groupBox1.Size = new System.Drawing.Size(360, 128);
			this.groupBox1.TabIndex = 0;
			this.groupBox1.TabStop = false;
			this.groupBox1.Text = "输入两个数字";
			// 
			// textBox1
			// 
			this.textBox1.Location = new System.Drawing.Point(56, 24);
			this.textBox1.Name = "textBox1";
			this.textBox1.TabIndex = 0;
			this.textBox1.Text = "111";
			// 
			// textBox2
			// 
			this.textBox2.Location = new System.Drawing.Point(56, 56);
			this.textBox2.Name = "textBox2";
			this.textBox2.TabIndex = 1;
			this.textBox2.Text = "345";
			// 
			// label1
			// 
			this.label1.Location = new System.Drawing.Point(8, 24);
			this.label1.Name = "label1";
			this.label1.Size = new System.Drawing.Size(40, 23);
			this.label1.TabIndex = 2;
			this.label1.Text = "数字1";
			// 
			// label2
			// 
			this.label2.Location = new System.Drawing.Point(8, 56);
			this.label2.Name = "label2";
			this.label2.Size = new System.Drawing.Size(40, 23);
			this.label2.TabIndex = 3;
			this.label2.Text = "数字2";
			// 
			// button1
			// 
			this.button1.Location = new System.Drawing.Point(192, 24);
			this.button1.Name = "button1";
			this.button1.Size = new System.Drawing.Size(144, 23);
			this.button1.TabIndex = 1;
			this.button1.Text = "使用Callback";
			this.button1.Click += new System.EventHandler(this.button1_Click);
			// 
			// button2
			// 
			this.button2.Location = new System.Drawing.Point(192, 56);
			this.button2.Name = "button2";
			this.button2.Size = new System.Drawing.Size(144, 23);
			this.button2.TabIndex = 4;
			this.button2.Text = "使用EndInvoke";
			this.button2.Click += new System.EventHandler(this.button2_Click);
			// 
			// button3
			// 
			this.button3.Location = new System.Drawing.Point(192, 88);
			this.button3.Name = "button3";
			this.button3.Size = new System.Drawing.Size(144, 23);
			this.button3.TabIndex = 5;
			this.button3.Text = "检测EndInvoke";
			this.button3.Click += new System.EventHandler(this.button3_Click);
			// 
			// Form1
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
			this.ClientSize = new System.Drawing.Size(360, 133);
			this.Controls.AddRange(new System.Windows.Forms.Control[] {
																		  this.groupBox1});
			this.Name = "Form1";
			this.Text = "Form1";
			this.groupBox1.ResumeLayout(false);
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// 应用程序的主入口点。
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Application.Run(new Form1());
		}

		private bool GetNumbers(out double x,out double y)
		{
			try
			{
				x=double.Parse(textBox1.Text);
				y=double.Parse(textBox2.Text);
				return true;
			}
			catch(Exception)
			{
				x=0;
				y=0;
				return false;
			}
		}

		private delegate double 除的委托(double x,double y);
		/// <summary>
		/// 这个方法是今次要异步执行的方法
		/// 因为它是作为From1的一个方法,所以能访问Form1的属性
		/// </summary>
		/// <param name="a"></param>
		/// <param name="b"></param>
		/// <returns>a/b</returns>
		private double 除(double a,double b)
		{
			//取得方法执行所在的线程
			Thread thisThread=Thread.CurrentThread;
			//在这个例子中,永远不成立。方法总是在其他线程中执行
			if(thisThread==this.theThread)
				throw(new Exception("if(thisThread==this.theThread)"));

			MessageBox.Show(DateTime.Now.ToLongTimeString()+"/n按确定计算"+a+"/"+b+"的结果");

			//如果b为0,那么就会抛出异常
			//后面会有处理异步调用的异常的说明
			return a/b;
		}

		#region CallBack调用例子
		/// <summary>
		/// 使用CallBack来处理异步调用
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void button1_Click(object sender, System.EventArgs e)
		{
			double a,b;
			if(!GetNumbers(out a,out b))
			{
				MessageBox.Show("请输入正确的数字");
				return;
			}

			//可以在这里重新"."一下,看看有没有BeginInvoke的方法显示在列表中?
			//定义是没有的,所以IDE没有显示出来。
			//不过编译器帮我们弄了这个方法,所以能编译通过
			IAsyncResult iar=new 除的委托(除).BeginInvoke(a,b,new AsyncCallback(当除完成调用),"使用CallBack");
			//关于BeginInvoke
			//new 除的委托(除) 这句不用多说了。
			//new 除的委托(除).BeginInvoke 是编译器自动生成的函数。
			//(a,b,new AsyncCallback(当除完成调用),"hello:)") 中
			//a,b 是和 除的委托 的定义是一致的
			//然后后面要加 AsyncCallback callback,object AsyncContext
			//看MSDN上对BeginInvoke的签名介绍。。
		}
		private void 当除完成调用(IAsyncResult iar)
		{
			//这个是对的。不过我找不到文档说明是不是始终是对的。
			System.Runtime.Remoting.Messaging.AsyncResult ar=(System.Runtime.Remoting.Messaging.AsyncResult)iar;
			//得到刚才的 new 除的委托(除)
			除的委托 d=(除的委托)ar.AsyncDelegate;
			double res;

			Thread thisThread=Thread.CurrentThread;
			string msg=thisThread==this.theThread?"/n这个线程和主线程是一致的":"/n这个线程和主线程是不同的";
			try
			{
				//和刚才的BeginInvoke像对应
				res=d.EndInvoke(iar);
				//EndInvoke只需要放个IAsyncResult来做结束调用标志就够了。
				//因为 除的委托 的定义,只有 In 参数,所以没有其他参数
				//看MSDN上对BeginInvoke的签名介绍。。


				MessageBox.Show("好了,,在 “除完成调用()”这个方法中,已经得到结果:/n"+res+msg);
			}
			catch(Exception x)
			{
				MessageBox.Show("好了,,在 “除完成调用()” 这个方法中检测到异常:/n"+x.Message+msg);
			}
		}
		#endregion

		#region 使用EndInvoke

		/// <summary>
		/// 这个是用来存放IAsyncResult的容器
		/// </summary>
		ArrayList al=new ArrayList();

		/// <summary>
		/// 使用EndInvoke来处理异步调用
		/// 执行完这个,按确定来处理新弹出来的MessageBox
		/// 然后按"检测EndInvoke"来看看结果。。
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void button2_Click(object sender, System.EventArgs e)
		{
			double a,b;
			if(!GetNumbers(out a,out b))
			{
				MessageBox.Show("请输入正确的数字");
				return;
			}

			//这个和上面的调用的最大区别就在参数AsyncCallback为null
			IAsyncResult iar=new 除的委托(除).BeginInvoke(a,b,null,"不使用Callback,直接使用iar.IsCompleted");
			al.Add(iar);
		}
		//测试看看有没有什么东东是已经完成的。。
		private void button3_Click(object sender, System.EventArgs e)
		{
			string msgs="好了,,在 “button3_Click()检测EndInvoke”这个方法中:";
			Thread thisThread=Thread.CurrentThread;
			string msg=thisThread==this.theThread?"/n这个线程和主线程是一致的":"/n这个线程和主线程是不同的";
			msgs+=msg+"/n/n";

			int countMax=al.Count;
			int count=0;
			ArrayList alDelete=new ArrayList();
			foreach(IAsyncResult iar in al)
			{
				//如果没有完成,看看下一个
				if(!iar.IsCompleted)continue;

				//好了。。这个iar代表的调用是完成了的。

				count++;

				//暂时不能修改al,所以只好这样
				alDelete.Add(iar);

				//和上面的用法一样。
				System.Runtime.Remoting.Messaging.AsyncResult ar=(System.Runtime.Remoting.Messaging.AsyncResult)iar;
				除的委托 d=(除的委托)ar.AsyncDelegate;
				double res;
				try
				{
					//同上
					res=d.EndInvoke(iar);
					msgs+=((string)iar.AsyncState)+"/n已经得到结果:/n"+res+"/n/n";
				}
				catch(Exception x)
				{
					msgs+=((string)iar.AsyncState)+"/n检测到异常:/n"+x.Message+"/n/n";
				}
			}
			//从al中删除已经执行完毕的调用的IAsyncResult
			foreach(IAsyncResult iar in alDelete)
			{
				al.Remove(iar);
			}

			if(countMax>0&&count==0)
				msgs+="倒,,还没有几个完成的。。";
			if(countMax==0)
				msgs="没有任何的调用啊。。";
			MessageBox.Show(msgs);
		}
		#endregion
	}
}

C#中的异步委托

异步委托默认情况下,执行一个委托实例操作是同步的,但委托实例同样可以使用成员函数BeginInvoke()进行异步回调。 BeginInvoke()除了接收原有委托签名的参数之外,参数表尾部额外带有两...
  • u011152627
  • u011152627
  • 2016年07月27日 11:30
  • 337

c#委托的异步调用 简单示例

委托的异步调用有时,如果要让委托去完成一个复杂耗时的任务时,同步调用不是一个好的选择,因为这样用户面临的是无聊的时间消耗和漫长(相对来说)的等待。这时委托的异步调用就体现出了优势,关于委托的异步调用C...
  • csharp25
  • csharp25
  • 2011年06月18日 11:35
  • 1853

[深入学习C#]完成异步委托的三种方式

简介  创建线程的一个简单方式是定义一个委托,并且异步调用它。委托是方法的类型安全的引用。Delegate类还支持异步地调用方法。在后台,Delegate类会创建一个执行任务的线程。线程  线程是程序...
  • honantic
  • honantic
  • 2015年07月07日 10:22
  • 24627

异步委托详解

在 使用BackgroundWorker组件 一文中,阐述了在Winform编程中,使用BackgroundWorker组件实现异步调用,本文主要讲述利用委托实现异步。 以下描述摘抄于MSDN: ...
  • everlasting51
  • everlasting51
  • 2015年04月29日 10:07
  • 772

委托,线程,同步,异步的学习(一)

线程这块一直没怎么去看过,今晚就来研究了下,委托与事件有一篇已经说过了,这里就不说了,主要研究委托和线程。委托主要有以下几个知识点: 一:什么是委托 二:什么时候用委托 三:多播委托 四:同步...
  • gghome
  • gghome
  • 2016年04月08日 00:32
  • 406

ASP.NET 委托,异步调用例子

 简要介绍:1.定义异步执行需要调用的方法2.定义具有与异步执行方法相同签名的委托(Delegate);3.调用 BeginInvoke 和 EndInvoke 方法。   3.1. BeginInv...
  • fdsa123456
  • fdsa123456
  • 2008年11月30日 11:13
  • 4712

c#使用委托实现异步调用

异步编程是受公共语言运行库的许多领域(如远程处理、ASP.NET 和 Windows 窗体)支持的功能。异步编程是 .NET Framework 中的核心概念。使用 .NET 异步编程,在程序继续执行...
  • tangpeicheng
  • tangpeicheng
  • 2006年12月03日 00:52
  • 4688

异步委托的应用(二) 有返回值的应用

上一次我们已经简单的了解了在没有返回值的情况下使用异步委托,可是有时候,我们在异步运行完之后,要给出一个结果性的东西,这怎么办呢。这就要用到返回值了。我想上篇中大家都看到了BeginInvoke这个方...
  • chenguang79
  • chenguang79
  • 2010年08月19日 17:31
  • 2019

取消或停止异步委托调用

  对于一般线程,我们可以abort来终止其执行,但由beginInvoke启动的委托调用,启用线程池线程执行,.Net没有赋予我们直接停止其调用的方法,由此,我们必须做些工作来实现。注意,试图操作线...
  • ChineseLiuxm
  • ChineseLiuxm
  • 2005年09月30日 14:16
  • 2135

C#使用委托进行异步编程

最近项目中需要用到异步编程,虽然以前研究过,但时间一长竟然就都忘了于是就又再重新学习了一遍…… 首先引用MSDN中的一段话来描述一下如何使用异步方式: .NET Framework 允许您异步调用任...
  • HELLO_THERE
  • HELLO_THERE
  • 2014年02月23日 23:23
  • 2072
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:一个编译器所支持的异步委托的例子
举报原因:
原因补充:

(最多只允许输入30个字)