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

最近有一个项目,需要对文件进行对比,说白一点就是数据库里存了文件的物理路径,你要用程序查一下,这些文件是否真实存在。当时没有想太多,就写了一个程序,发现程序直接就卡死。因为数据量比较大,上百万条,而且你也不知道这个数据对比到哪里了。 这时候就想到了用异步来处理,上网查了一下。网上也有很多文章,但是我看了好几天才看明白,本人比较笨,而且以前没有用过异步。

为了让自己记得更准备和扎实一些,我就把我学习的一些经历和方法记录下来,如果有朋友感觉不对,或是有更好的方法,希望告知,我在这里十分感谢了。

这里面有一些基本的定义,我就找了一些网上的文章的片断,我个人认为很不错。很好理解

一,我们为什么要用异步

 

  离你很远的地方有个很漂亮的女网友,你想知道她到底对你如何,你通过邮政礼仪,寄给她一支玫瑰(相当于异步调用)。因为回执要等很多天,所以,你这 些天不必整天傻等回执,可以照样吃饭工作(处理些简单的事务),当然,如果你这些天又泡到个MM,这时你就要选择,如果也用异步的方法,当然没问题,因为 哪个回 执先回来,先处理那个,但如果你对后面这个MM采用同步方式,那你只能解决掉这个同步的MM后,才能处理前面那个回执,不管那个回执何时到达。 

 

二,委托是什么?

 

  委 托其实就等于C++里面的函数指针,是指向函数地址的变量。我想,也许是为了更加面向对象,并且避免指针的滥用而导致系统错误,C#引用了委托这个概念。 其实不管是事件,还是委托,大家都可以把它们看成跟类一样的东西,都需要声明,都需要进行实例化,并且其实例可以看成引用类型的对象。这样的话,更加容易 理解很多觉得很神秘的东西。

委托就是声明一个“函数指针”,但这个“指针”必须要声明其指向函数的形式。

 

 

知道了这些,我们就用一个小例子来看一下他是怎么完成的。我做的例子比较简单,就是一个算一个从1加到10的方法。

 

在前台我建立了三个控件,二个textbox,一个button,分别是txtNum用来显示计算过程的页面。txtInfo用来显示一些相关的信息,主要是让大家看一下他是否进行了异步操作。btnAdd就是一个计数的按钮了

 

//定义一个没有返回值的委托,处了多了一个delegate是不是和定义函数没有什么区别
public delegate void getNums();

 

 

/// <summary>
/// 无返回值调用方法,用来计数,这里我用了一个Thread.sleep(500)这个大家都应该明白是什么意思,就是让它暂停半秒钟
/// 只有这样,我们才能看到它的变化。

/// *****这里我要说明一点的是,这个函数是要被委托调用的,所以它要与委托的定义方式一样。代不代参数和有没有返回值都要与委托一///样********
/// </summary>
        public void GetNum()
        {
            for (int i = 1; i <= 10; i++)
            {
                this.txtNum.Text = (Convert.ToInt32(this.txtNum.Text.Trim()) + i).ToString();
                Thread.Sleep(500);
            }

            this.txtInfo.Text = "结束计数";
        }

 

 

好,委托我们定义好了,要计数的方法函数我们也定义好了,下面就要在点按钮的时候来运行它了。

 

 

大家可能都知道,在我们进行异步操作的时候,程序已经都给我们建立好了,一些前面代begin的方法。基本上你要进行异步的时候,都会有相对应与同步的方法一样的只是前面加了一个begin的方法。最常见的,就是file.beginRead

 

 

      private void btnAdd_Click(object sender, EventArgs e)
        {
            this.txtInfo.Text = "开始计数";

            //这里初始化一下委托,这里要说明的是,委托中调用的函数不用加()只要一个名字就行了。
            getNums gn = new getNums(GetNum);

            //委托中的BeginInvoke里面有二个参数

      //一个回调函数callback .类型:System. AsyncCallback
            //工作流已完成后要调用的方法。

      //另一个是一个object类型的参数。在后面一节中我们会用到它
            //因为我们没有任何的返回值,所以BeginInvoke里面就是给null
            gn.BeginInvoke(null, null);

            //这里你可以再做一些别的
        }

 

好了,我们试一下吧。看一下结果,

这时候一定会出现错误,说txtNum控件不在此线程中。这是因为你异步调用的时候调用了不在此线程中建立的控件。才会报这个错误。我们用一个最简单的方法来解决,但是我不建议大家使用。以后我们会说到底用什么方法比较好。

 

 

我们在

 public Form1()
        {
            InitializeComponent();

 

      //就是加入这个值

            Form.CheckForIllegalCrossThreadCalls = false;
        }

 

是不是在txtNum中,显示出了数字在变化。这时候你拖动一下窗体,它是可以拖动的。而且它在计数完成之后你会发现,你会发现txtInfo的值变了。你可能会说,这个没看出有什么异步啊。你在gn.BeginInvoke(null, null);这句的后面加一个this.txtInfo.Text = "我正在计数";你就会发现了,你在计数的时候,程序还可以再去做别的东西。

 

是不是很有意思,也很简单。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值