zoukankan      html  css  js  c++  java
  • 一起谈.NET技术,C#基础之委托异步 狼人:

      大家知道委托就相当于C++里面的函数指针,相信大家都很很了解,看看如下简单代码来回想一下委托

    public delegate void Ad();
    xu xus
    = new xu();
    Ad b
    = new Ad(xus.Add);
    b
    += xus.ex;
    b();
    Console.ReadLine();
    class xu
    {
    public void Add()
    {
    //Thread.Sleep(5000);
    Console.WriteLine("sssssssssssssssssssss");
    }
    public void ex()
    {
    //Thread.Sleep(5000);
    Console.WriteLine("aaaaaaaaaaaaaaaaaaaaa");
    }
    }

      这里我们看见 定义了一个ADD 的委托没有参数没有返回值 然后把委托指向ADD 和ex 两个方法(多播委托) 然后执行b()  执行之后 结果大家应该知道 就是执行了这2个方法打印出 "ssssssssssssss"于"aaaaaaaaaaaaaaaa"。那如果变成下面这个形式呢?

    public delegate int Ad(int x,int y);
    static void Main(string[] args)
    {
    xu xus
    = new xu();
    Ad a
    = new Ad(Add);
    a
    += (int x, int y) => { return x - y; };
    Console.WriteLine(a(
    3,2));
    Console.ReadLine();
    }
    static int Add(int x, int y)
    {
    //Thread.Sleep(2000);
    return x + y;
    }
    static int ex(int x, int y)
    {
    //Thread.Sleep(5000);
    return x - y;
    }
    }

      这段代码 也是执行一个多播委托 但是输出的结果会是什么样的呢 答案是 输出1,为什么前面那个委托会输出2个方法 而这个委托只会输出第二个方法的返回值?如果我们也想输出2个返回值怎么办呢?其实很简单 代码如下

    public delegate int Ad(int x,int y);
    static void Main(string[] args)
    {
    xu xus
    = new xu();
    Ad a
    = new Ad(Add);
    a
    += (int x, int y) => { return x - y; };
    Delegate[] d
    = a.GetInvocationList();
    for (int i = 0; i < d.Length; i++)
    {
    if (d[i] is Ad)
    {
    Ad s
    = (Ad)d[i];
    Console.WriteLine(s(
    3, 2));
    }
    }
    Console.ReadLine();
    }
    static int Add(int x, int y)
    {
    // Thread.Sleep(2000);
    return x + y;
    }
    static int ex(int x, int y)
    {
    //Thread.Sleep(5000);
    return x - y;
    }
    }

      这里我们使用了一个GetInvocationList 方法来返回多播委托的调用列表 然后转化ad 然后循环调用 最后显示的结果就是5,1。委托的 复习我们就看到这里 现在回到正题 看看委托的异步调用。

    public delegate int Ad(int x,int y);
    static void Main(string[] args)
    {
    xu xus
    = new xu();
    Ad a
    = new Ad(Add);
    Console.WriteLine(a(
    3, 3));
    Console.WriteLine(
    "start");
    Console.ReadLine();
    }
    static int Add(int x, int y)
    {
    Thread.Sleep(
    2000);
    return x + y;
    }

      运行这段代码 会先停顿2秒钟之后再显示6 和start 因为我使用了sleep这个方法 它使该线程休眠2秒钟,所以会在2秒之后显示信息,但是这对用户体验来说是非常糟糕的,那我们怎么改善呢?看看如下代码

    public delegate int Ad(int x,int y);
    static void Main(string[] args)
    {
    xu xus
    = new xu();
    Ad a
    = new Ad(Add);
    Console.WriteLine(a(
    3, 3));
    // Console.WriteLine("start");
    IAsyncResult isa= a.BeginInvoke(3, 3, null, null);
    while (!isa.IsCompleted)
    {
    Console.WriteLine(
    "未完成");
    }
    int s= a.EndInvoke(isa);
    Console.WriteLine(s.ToString());
    Console.ReadLine();
    }
    static int Add(int x, int y)
    {
    Thread.Sleep(
    2000);
    return x + y;
    }
    static int ex(int x, int y)
    {
    //Thread.Sleep(5000);
    return x - y;
    }

      这里我们使用了begininvoke方法来异步执行 委托方法返回一个IAsyncResult 类型的值 代表委托执行的状态,使用一个while循环 来判断IsCompleted 如果没有完成异步调用则不断显示“未完成” 如果完成endinvoke 则返回结果。但是这里需要不断的询问操作完成状态 那么我们怎样让委托异步调用完成之后主动通知我们呢? 看看如下代码

    public delegate int Ad(int x,int y);
    static void Main(string[] args)
    {
    xu xus
    = new xu();
    Ad a
    = new Ad(Add);
    Console.WriteLine(a(
    3, 3));
    IAsyncResult isa
    = a.BeginInvoke(3, 3, new AsyncCallback(call), "edit by xyl");
    //执行你想执行的代码 这里我们还是用IsCompleted来代替
    while (!isa.IsCompleted)
    {
    Console.WriteLine(
    "未完成");
    }
    Console.ReadLine();
    }
    static void call(IAsyncResult isa)
    {
    AsyncResult ar
    = (AsyncResult)isa;
    Ad a
    = (Ad)ar.AsyncDelegate;
    Console.WriteLine(
    "this is {0},{1}",a.EndInvoke(isa),ar.AsyncState);
    }

    static int Add(int x, int y)
    {
    Thread.Sleep(
    2000);
    return x + y;
    }
    static int ex(int x, int y)
    {
    //Thread.Sleep(5000);
    return x - y;
    }
    }

      这里我们使用了一个call方法 注意它是没有返回值的。把IAsyncResult转换成AsyncResult注意少了个I然后转换成AD 类型的委托 最后endinvoke 来返回值 这样在委托异步执行完成之后会自动通知方法。呵呵 好了今天就说到这里吧。如果有说的不对的地方欢迎指正 大家一起学习一起进步。

  • 相关阅读:
    [转]tomcat启动报错too low setting for -Xss
    linux(centos) tomcat设置开机启动
    docker--centos镜像安装tomcat jdk1.8 mysql部署java web项目
    docker--常用命令
    docker--容器和镜像的导入导出及部署
    docker--在centos镜像安装mysql
    docker--(MAC ubuntu centos)安装
    js常用判断和语法
    linux命令-crontab
    ajax的另一种成功和失败回调函数
  • 原文地址:https://www.cnblogs.com/waw/p/2163091.html
Copyright © 2011-2022 走看看