zoukankan      html  css  js  c++  java
  • 异步调用和多线程调用

    同步方法和异步方法的区别

    同步方法调用在程序继续执行之前需要等待同步方法执行完毕返回结果;
    异步方法则在被调用之后立即返回以便程序在被调用方法完成其任务的同时执行其它操作

    现在新建一个Windows应用程序,然后放上一个button1,写入以下代码:

    C# code
    private void button1_Click(object sender, EventArgs e) { bigFunc(); button1.Text = "finished"; } private void bigFunc() { string s = null; for (int i = 0; i < 65535; i++) { s += i.ToString(); } }




    点击该按钮后,发现程序卡死了很久才出现"finished"的字样。


    现在请使用委托与异步调用的方法来解决此问题,让程序不卡死,求具体代码。

    异步处理

    楼主是想把 bigFunc() 异步执行吧

    异步模式常用的有 等待, 轮询, 回调等方式。

    执行代理的BeginInvoke方法,会立既返回当前线程
     
     调用EndInvoke等待方法完成,阻塞当前线程 

    等待模式 

      方法代理.BeginInvoke
      可能这个方法执行的时间比较长,调用BeginInvoke后可以做一些其他工作,真到调用完成
    方法代理.EndInvoke  
        代理执行完成.这里方法没执行完,阻塞当前线程

     异步代理的非阻塞模式 方法回调: 以楼主的代码做例子

      public delegate void MyDelegate();  //新建无参数代理
      private void bigFunc() { string s = null; for (int i = 0; i < 65535; i++) { s += i.ToString(); } }

    private void button1_Click(object sender, EventArgs e)
            {

                MyDelegate md = bigFunc; //设置代理的方法
              // IAsyncResult 唯一标识了通过BeginInvoke调用的方法
              IAsyncResult iasync = md.BeginInvoke(OnMethodCompletion, null);
            }
      void OnMethodCompletion(IAsyncResult async)  //这个方法会在异步执行完成后由系统调用
            {
                AsyncResult asyncResult = (AsyncResult)async; 
                MyDelegate md = (MyDelegate)asyncResult.AsyncDelegate;//源代理 
                md.EndInvoke(asyncResult); 
            }

     这个界面不阻塞,并不像10楼说的.不信试试
     

    你当前这个例子 ,回调方式最适合,就我给的例子。

    异步方法.BeginInvoke(...)
    异步方法.EndInvoke(...)
     ...
    这个和直接调用方法差不多, 因为调用  异步方法.EndInvoke,系统会等待 异步方法执行完成,才会执行下面的方法。


    异步方法.BeginInvoke(...)
      dosomething 这里做点什么  因为要异步计算的方法可能耗时比较常,调用BeginInvoke以后在做点其他事
     等你事情做完后,
    异步方法.EndInvoke(...) 在调用EndInvoke ,一直等到异步执行完成才会执行下面的行. 也就是说中间做什么事和你的异
    步方法是同时进行的,只是调用EndInvoke如果方法已执行完成,立既返回当前线程了,如果没完成,继续等待,这时就和同步
    时的情况差不多,主线程一样会锁死。

    轮循和这个差不多 ,只是保存了一个IAsyncResult, 来查询方法是否执行完成,只不过还可以轮循多个异步代理

    回调 ,调用  异步方法.BeginInvoke(参数,回调方法),  后不用去管它,处理完成后由回调方法发送通知。

    等待模式 就像是你找了个人去做事, 要等他做完了你才能做后面的事,当然,在他做事的时候你可以干点别的,不过要等他干完,你才能策底做完,这其间你虽然可以做别的,但是你也不知道你的事先做完还是他的事先做完,你先完成了就要等他.

    轮循模式 找了个几笨蛋去做事,  你也不知道他们什么时候完成,于是,过一会问他们,你做完了吗,你做完了吗。。

    回调模式 这次找了个足够聪明的人做事, 你只要告诉他做什么,他会勤勤恳恳的的帮你完成,完成后会主动告诉你,boss,我的事做完啦,这是你要的处理结果,笑纳。 你不用去管过程,放心做你的事,等着他来报告就行了

    IAsyncResult iasync = md.BeginInvoke(OnMethodCompletion, null); //我理解为开始执行bigFunc()方法,但在此处声明的IAsyncResult iasync并赋值在这里是起什么作用  ,这里的其实没用,如果不是用回调通知,那么用它来查询方法状态


    //此方法执行完bigFunc()方法后自动会被调用,所以叫回调函数,呵呵。但是都结束了,还回调一下做什么呢?

    异步代理实际上是放在系统线程池里执行,IAsyncResult就像一个标签,唯一标名一个代理方法。  BeginInvoke(OnMethodCompletion... 这里会传参数IAsyncResult给方法OnMethodCompletion.

    为什么要回调? 不回调你就不知道他做没做完,并且代理是可以有返回值的,否则你就无法获取到方法返回的值.
    异步方法进入线程池执行完毕后通知回调方法,也就是调用OnMethodCompletion


    AsyncResult asyncResult = (AsyncResult)async;//这是干什么呢? 
      这就像一个签名,记录了代理方法,查询等  
        MyDelegate md = (MyDelegate)asyncResult.AsyncDelegate;//这又是干什么呢?  
    这就是你一开始声明的代理  相当于前面设置了  asyncResult.AsyncDelegate=md; 这里在取出来

    线程处理

    namespace Threads
    {
       
    public partial class Form2 : Form
        {
           
    public Form2()
            {
                InitializeComponent();
            }
            Thread th,th2;
           
    public delegate void SetDelegate();

           
    private void button1_Click(object sender, EventArgs e)
            {
                th
    = new Thread(new ThreadStart(fill));
                th.Start();
                th2
    = new Thread(new ThreadStart(SetButton));
                th2.Start();
            }
           
    private void fill()
            {
               
    string s = "";
               
    for (int i = 0; i < 8550; i++)
                {
                    s
    += i.ToString()+" ";
                }
            }

           
    private void SetButton()
            {
               
    if (button1.InvokeRequired)
                {
                    Invoke(
    new SetDelegate(SetButton), new object[] {  });
                }
               
    else
                {
                   
    this.button1.Text = "finished";
                }
               
            }
        }
    }

     


       本人博客的文章大部分来自网络转载,因为时间的关系,没有写明转载出处和作者。所以在些郑重的说明:文章只限交流,版权归作者。谢谢

  • 相关阅读:
    Linux命令行界面使用代理上网
    .NET 开发框架 代码生成器
    如何正确地学习
    Ubuntu实用命令——不断更新中......
    MSSQL如何快速清除数据库日志转,经实践有效
    C# 获取机器码
    C#中得到每周,每月,每季,每年的年初末日期
    asp.net(C#)解析Json的类代码
    由拖库攻击谈口令字段的加密策略(数据库加密)
    用sql查询当天,一周,一个月的数据
  • 原文地址:https://www.cnblogs.com/wzg0319/p/1631385.html
Copyright © 2011-2022 走看看