美文网首页
IAsyncResult异步编程

IAsyncResult异步编程

作者: 简单一点点 | 来源:发表于2020-12-15 15:17 被阅读0次

IAsyncResult 异步设计模式通过名为 BeginOperationName 和 EndOperationName 的两个方法来实现原同步方法的异步调用,如 FileStream 类提供了 BeginRead 和 EndRead 方法来从文件异步读取字节,它们是 Read 方法的异步版本。

IAsyncResult接口:

public interface IAsyncResult  
{  
   // 获取用户定义的对象,该对象限定或包含有关异步操作的信息。
   object AsyncState { get; }  
   // 获取用于等待异步操作完成的WaitHandle。
   WaitHandle AsyncWaitHandle { get; }  
   // 获取一个值,该值指示异步操作是否同步完成。
   bool CompletedSynchronously { get; }  
   // 获取一个值,该值指示异步操作是否已完成。
   bool IsCompleted { get; }  
} 

补充说明:WaitHandle用来封装等待对共享资源进行独占访问的操作系统特定的对象。它是一个抽象类,我们一般不直接用,而是用它的派生类:

  • AutoResetEvent:表示线程同步事件在一个等待线程释放后收到信号时自动重置。 此类不能被继承。
  • ManualResetEvent:表示线程同步事件,收到信号时,必须手动重置该事件。 此类不能被继承。
  • EventWaitHandle:表示一个线程同步事件。结合了前2个。

使用示例

下面了解一些详细使用。

用委托(Delegate)的 BeginInvoke 和 EndInvoke 方法操作线程

BeginInvoke 方法可以使用线程异步地执行委托所指向的方法。然后通过 EndInvoke 方法获得方法的返回值(EndInvoke 方法的返回值就是被调用方法的返回值),或是确定方法已经被成功调用。

class Program
{
    private delegate int NewTaskDelegate(int ms);
    static void Main(string[] args)
    {
        NewTaskDelegate task = NewTask;
        IAsyncResult asyncResult = task.BeginInvoke(2000, null, null);
        // //EndInvoke方法将被阻塞2秒
        int result = task.EndInvoke(asyncResult);
        Console.WriteLine(result);
        Console.Read();
    }

    private static int NewTask(int ms)
    {
        Console.WriteLine("任务开始");
        Thread.Sleep(ms);
        Random random = new Random();
        int n = random.Next(10000);
        Console.WriteLine("任务完成");
        return n;
    }
}

使用IAsyncResult.IsCompleted属性来判断异步调用是否完成

class Program
{
    private delegate int NewTaskDelegate(int ms);
    static void Main(string[] args)
    {
        NewTaskDelegate task = NewTask;
        IAsyncResult asyncResult = task.BeginInvoke(2000, null, null);
        // 等待异步执行完成
        while (!asyncResult.IsCompleted)
        {
            Console.Write("*");
            Thread.Sleep(100);
        }
        // 由于异步调用已经完成,因此, EndInvoke会立刻返回结果
        int result = task.EndInvoke(asyncResult);
        Console.WriteLine(result);
        Console.Read();
    }

    private static int NewTask(int ms)
    {
        Console.WriteLine("任务开始");
        Thread.Sleep(ms);
        Random random = new Random();
        int n = random.Next(10000);
        Console.WriteLine("任务完成");
        return n;
    }
}

使用WaitOne方法等待异步方法执行完成

WaitOne的第一个参数表示要等待的毫秒数,在指定时间之内,WaitOne方法将一直等待,直到异步调用完成,并发出通知,WaitOne方法才返回true。当等待指定时间之后,异步调用仍未完成,WaitOne方法返回false,如果指定时间为0,表示不等待,如果为-1,表示永远等待,直到异步调用完成。

class Program
{
    private delegate int NewTaskDelegate(int ms);
    static void Main(string[] args)
    {
        NewTaskDelegate task = NewTask;
        IAsyncResult asyncResult = task.BeginInvoke(2000, null, null);
        // 等待异步执行完成
        while (!asyncResult.AsyncWaitHandle.WaitOne(100, false))
        {
            Console.WriteLine("*");
        }
        // 由于异步调用已经完成,因此, EndInvoke会立刻返回结果
        int result = task.EndInvoke(asyncResult);
        Console.WriteLine(result);
        Console.Read();
    }

    private static int NewTask(int ms)
    {
        Console.WriteLine("任务开始");
        Thread.Sleep(ms);
        Random random = new Random();
        int n = random.Next(10000);
        Console.WriteLine("任务完成");
        return n;
    }
}

使用回调方法获取返回值

class Program
{
    private delegate int NewTaskDelegate(int ms);
    static void Main(string[] args)
    {
        NewTaskDelegate task = NewTask;
        IAsyncResult asyncResult = task.BeginInvoke(2000, MethodCompleted, task);
        Console.Read();
    }

    private static int NewTask(int ms)
    {
        Console.WriteLine("任务开始");
        Thread.Sleep(ms);
        Random random = new Random();
        int n = random.Next(10000);
        Console.WriteLine("任务完成");
        return n;
    }

    private static void MethodCompleted(IAsyncResult asyncResult)
    {
        if (asyncResult == null || asyncResult.AsyncState == null)
        {
            Console.WriteLine("回调失败!!!");
            return;
        }
        int result = (asyncResult.AsyncState as NewTaskDelegate).EndInvoke(asyncResult);
        Console.WriteLine("任务完成,结果:" + result);
    }
}

重点需要注意BeginInvoke方法的参数传递方式:

前面是其委托本身的参数。 倒数第二个参数(MethodCompleted)是回调方法委托类型,他是回调方法的委托,此委托没有返回值,有一个IAsyncResult类型的参数,当method方法执行完后,系统会自动调用MethodCompleted方法。 最后一个参数(task)需要向MethodCompleted方法中传递一些值,一般可以传递被调用方法的委托,这个值可以使用IAsyncResult.AsyncState属性获得。

相关文章

  • IAsyncResult异步编程

    IAsyncResult 异步设计模式通过名为 BeginOperationName 和 EndOperation...

  • ES6学习--异步编程--Generator

    异步编程 : (异步编程的语法目的就是让异步编程更像同步编程) 回调函数利用回调函数实现异步编程本身没有问题, 问...

  • JavaScript异步编程好文摘要

    JavaScript之异步编程简述JavaScript异步编程

  • 认识异步编程

    认识异步编程 本章主要介绍异步编程的概念和作用,Java中异步编程的场景以及不同异步编程场景应使用什么技术实现。 ...

  • part1整理

    函数式编程:JavaScript函数式编程指南 异步编程:异步编程 Promise源码 JavaScript基础知...

  • 论异步编程

    相信本书介绍了CompletableFuture,大家就会认识到什么是异步编程。异步编程的好处。 异步编程最大好处...

  • 读书笔记#Java异步编程实战-上

    Java异步编程实战 chap1 认识异步编程 异步编程概念与作用在使用同步编程方式时,由于每个线程同时只能发起一...

  • Combine 基础知识

    摘自《SwiftUI和Combine编程》---《Combine异步编程》 响应式异步编程模型 将“状态变化”看作...

  • 关于node.js的那些事(四)—异步编程的优势与难点

    有异步I/O,必有异步编程。异步编程有它的优势,也有它的难点,下面我们就这门语言异步编程的优势和难点来展开谈...

  • 异步编程的前世今生

    异步编程的前世今生 1、为什么需要异步编程 异步编程是相对同步编程来说的,开发项目时,开发者总是希望,程序的执行顺...

网友评论

      本文标题:IAsyncResult异步编程

      本文链接:https://www.haomeiwen.com/subject/upjwgktx.html