MSDN搬运 之 [使用 IAsyncResult 调用异步方法]

使用 IAsyncResult 调用异步方法

.NET Framework 和第三方类库中的类型可以提供允许应用程序在主应用程序线程之外的线程中执行异步操作的同时继续执行的方法。下面几部分介绍了在调用使用 IAsyncResult 设计模式的异步方法时可以采用的几种不同方式,并提供了演示这些方式的代码示例。

  • 通过结束异步操作来阻止应用程序执行。
  • 使用 AsyncWaitHandle 阻止应用程序的执行。
  • 轮询异步操作的状态。
  • 使用 AsyncCallback 委托结束异步操作。

通过结束异步操作来阻止应用程序执行

如果应用程序在等待异步操作结果时不能继续执行其他工作,则在操作完成之前,必须阻止执行其他工作。可以使用下列方法之一来在等待异步操作完成时阻止应用程序的主线程。

在异步操作完成之前使用 EndOperationName 方法阻止的应用程序通常会调用 BeginOperationName 方法,执行任何不需要等待异步操作的结果也可以执行的工作,然后调用 EndOperationName

示例

下面的代码示例演示如何使用 Dns 类中的异步方法来检索用户指定的计算机的域名系统信息。请注意,示例中为 BeginGetHostByNamerequestCallback 和 stateObject 参数传递了 null(在 Visual Basic 中为 Nothing),因为在使用此方法时不需要这两个参数。

复制

/*
The following example demonstrates using asynchronous methods to
get Domain Name System information for the specified host computer.
*/

using System;
using System.Net;
using System.Net.Sockets;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class BlockUntilOperationCompletes
    {
        public static void Main(string[] args)
        {
            // Make sure the caller supplied a host name.
            if (args.Length == 0 || args[0].Length == 0)
            {
                // Print a message and exit.
                Console.WriteLine("You must specify the name of a host computer.");
                return;
            }
            // Start the asynchronous request for DNS information.
            // This example does not use a delegate or user-supplied object
            // so the last two arguments are null.
            IAsyncResult result = Dns.BeginGetHostEntry(args[0], null, null);
            Console.WriteLine("Processing your request for information...");
            // Do any additional work that can be done here.
            try
            {
                // EndGetHostByName blocks until the process completes.
                IPHostEntry host = Dns.EndGetHostEntry(result);
                string[] aliases = host.Aliases;
                IPAddress[] addresses = host.AddressList;
                if (aliases.Length > 0)
                {
                    Console.WriteLine("Aliases");
                    for (int i = 0; i < aliases.Length; i++)
                    {
                        Console.WriteLine("{0}", aliases[i]);
                    }
                }
                if (addresses.Length > 0)
                {
                    Console.WriteLine("Addresses");
                    for (int i = 0; i < addresses.Length; i++)
                    {
                        Console.WriteLine("{0}",addresses[i].ToString());
                    }
                }
            }
            catch (SocketException e)
            {
                Console.WriteLine("An exception occurred while processing the request: {0}", e.Message);
            }
        }
    }
}

使用 AsyncWaitHandle 阻止应用程序的执行

如果应用程序在等待异步操作结果时不能继续执行其他工作,则在操作完成之前,必须阻止执行其他工作。可以使用下列方法之一来在等待异步操作完成时阻止应用程序的主线程。

那些在异步操作完成前一直使用一个或多个 WaitHandle 对象阻止其他操作的应用程序通常会调用 BeginOperationName 方法,执行不需要等待操作结果的工作,然后一直等到异步操作完成才停止阻止。通过使用 AsyncWaitHandle 调用 WaitOne 方法之一,应用程序可以阻止一个操作。若要在等待一组异步操作完成期间阻止执行,应将相关的 AsyncWaitHandle 对象存储在数组中,然后调用 WaitAll 方法之一。若要在等待一组异步操作中的任一操作完成时阻止其他操作,应将关联的 AsyncWaitHandle 对象存储在数组中,然后调用 WaitAny 方法之一。

示例

下面的代码示例演示如何使用 DNS 类中的异步方法来检索用户指定的计算机的域名系统信息。此示例演示如何使用与异步操作关联的 WaitHandle 来阻止。请注意,示例中为 BeginGetHostByNamerequestCallback 和 stateObject 参数传递了 null(在 Visual Basic 中为 Nothing),因为使用此方法时不需要这两个参数。

复制

/*
The following example demonstrates using asynchronous methods to
get Domain Name System information for the specified host computer.

*/

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class WaitUntilOperationCompletes
    {
        public static void Main(string[] args)
        {
            // Make sure the caller supplied a host name.
            if (args.Length == 0 || args[0].Length == 0)
            {
                // Print a message and exit.
                Console.WriteLine("You must specify the name of a host computer.");
                return;
            }
            // Start the asynchronous request for DNS information.
            IAsyncResult result = Dns.BeginGetHostEntry(args[0], null, null);
            Console.WriteLine("Processing request for information...");
            // Wait until the operation completes.
            result.AsyncWaitHandle.WaitOne();
            // The operation completed. Process the results.
            try
            {
                // Get the results.
                IPHostEntry host = Dns.EndGetHostEntry(result);
                string[] aliases = host.Aliases;
                IPAddress[] addresses = host.AddressList;
                if (aliases.Length > 0)
                {
                    Console.WriteLine("Aliases");
                    for (int i = 0; i < aliases.Length; i++)
                    {
                        Console.WriteLine("{0}", aliases[i]);
                    }
                }
                if (addresses.Length > 0)
                {
                    Console.WriteLine("Addresses");
                    for (int i = 0; i < addresses.Length; i++)
                    {
                        Console.WriteLine("{0}",addresses[i].ToString());
                    }
                }
            }
            catch (SocketException e)
            {
                Console.WriteLine("Exception occurred while processing the request: {0}",
                    e.Message);
            }
        }
    }
}

轮询异步操作的状态

在等待异步操作结果的同时可以进行其他工作的应用程序不应在操作完成之前阻止等待。可以使用下列方法之一来在等待异步操作完成的同时继续执行指令。

示例

下面的代码示例演示如何使用 Dns 类中的异步方法来检索用户指定的计算机的域名系统信息。此示例开始异步操作,然后在控制台输出句点(“.”),直到操作完成。请注意,示例中为 BeginGetHostByNameAsyncCallbackObject 参数传递了 null(在 Visual Basic 中为 Nothing),因为在使用此方法时不需要这两个参数。

复制

/*
The following example demonstrates using asynchronous methods to
get Domain Name System information for the specified host computer.
This example polls to detect the end of the asynchronous operation.
*/

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class PollUntilOperationCompletes
    {
        static void UpdateUserInterface()
        {
            // Print a period to indicate that the application
            // is still working on the request.
            Console.Write(".");
        }
        public static void Main(string[] args)
        {
            // Make sure the caller supplied a host name.
            if (args.Length == 0 || args[0].Length == 0)
            {
                // Print a message and exit.
                Console.WriteLine("You must specify the name of a host computer.");
                return;
            }
            // Start the asychronous request for DNS information.
            IAsyncResult result = Dns.BeginGetHostEntry(args[0], null, null);
            Console.WriteLine("Processing request for information...");

            // Poll for completion information.
            // Print periods (".") until the operation completes.
            while (result.IsCompleted != true)
            {
                UpdateUserInterface();
            }
            // The operation is complete. Process the results.
            // Print a new line.
            Console.WriteLine();
            try
            {
                IPHostEntry host = Dns.EndGetHostEntry(result);
                string[] aliases = host.Aliases;
                IPAddress[] addresses = host.AddressList;
                if (aliases.Length > 0)
                {
                    Console.WriteLine("Aliases");
                    for (int i = 0; i < aliases.Length; i++)
                    {
                        Console.WriteLine("{0}", aliases[i]);
                    }
                }
                if (addresses.Length > 0)
                {
                    Console.WriteLine("Addresses");
                    for (int i = 0; i < addresses.Length; i++)
                    {
                        Console.WriteLine("{0}",addresses[i].ToString());
                    }
                }
            }
            catch (SocketException e)
            {
                Console.WriteLine("An exception occurred while processing the request: {0}", e.Message);
            }
        }
    }
}

使用 AsyncCallback 委托结束异步操作

在等待异步操作结果的同时可以进行其他工作的应用程序不应在操作完成之前阻止等待。可以使用下列方法之一来在等待异步操作完成的同时继续执行指令。

  • 可使用 AsyncCallback 委托来处理另一个线程中的异步操作的结果。本主题中演示了此方法。
  • 可使用异步操作的 BeginOperationName 方法返回的 IAsyncResultIsCompleted 属性来确定此操作是否已完成。有关演示此方法的示例,请参见轮询异步操作的状态

示例

下面的代码示例演示如何使用 Dns 类中的异步方法来检索用户指定的计算机的域名系统 (DNS) 信息。此示例创建了引用 ProcessDnsInformation 方法的 AsyncCallback 委托。对各个针对 DNS 信息发出的异步请求,将分别调用一次此方法。

请注意,用户指定的主机被传递给了 BeginGetHostByNameObject 参数。有关演示如何定义和使用更复杂的状态对象的示例,请参见使用 AsyncCallback 委托和状态对象

复制

/*
The following example demonstrates using asynchronous methods to
get Domain Name System information for the specified host computers.
This example uses a delegate to obtain the results of each asynchronous
operation.
*/

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections.Specialized;
using System.Collections;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class UseDelegateForAsyncCallback
    {
        static int requestCounter;
        static ArrayList hostData = new ArrayList();
        static StringCollection hostNames = new StringCollection();
        static void UpdateUserInterface()
        {
            // Print a message to indicate that the application
            // is still working on the remaining requests.
            Console.WriteLine("{0} requests remaining.", requestCounter);
        }
        public static void Main()
        {
            // Create the delegate that will process the results of the
            // asynchronous request.
            AsyncCallback callBack = new AsyncCallback(ProcessDnsInformation);
            string host;
            do
            {
                Console.Write(" Enter the name of a host computer or <enter> to finish: ");
                host = Console.ReadLine();
                if (host.Length > 0)
                {
                    // Increment the request counter in a thread safe manner.
                    Interlocked.Increment(ref requestCounter);
                    // Start the asynchronous request for DNS information.
                    Dns.BeginGetHostEntry(host, callBack, host);
                 }
            } while (host.Length > 0);
            // The user has entered all of the host names for lookup.
            // Now wait until the threads complete.
            while (requestCounter > 0)
            {
                UpdateUserInterface();
            }
            // Display the results.
            for (int i = 0; i< hostNames.Count; i++)
            {
                object data = hostData [i];
                string message = data as string;
                // A SocketException was thrown.
                if (message != null)
                {
                    Console.WriteLine("Request for {0} returned message: {1}",
                        hostNames[i], message);
                    continue;
                }
                // Get the results.
                IPHostEntry h = (IPHostEntry) data;
                string[] aliases = h.Aliases;
                IPAddress[] addresses = h.AddressList;
                if (aliases.Length > 0)
                {
                    Console.WriteLine("Aliases for {0}", hostNames[i]);
                    for (int j = 0; j < aliases.Length; j++)
                    {
                        Console.WriteLine("{0}", aliases[j]);
                    }
                }
                if (addresses.Length > 0)
                {
                    Console.WriteLine("Addresses for {0}", hostNames[i]);
                    for (int k = 0; k < addresses.Length; k++)
                    {
                        Console.WriteLine("{0}",addresses[k].ToString());
                    }
                }
            }
       }

        // The following method is called when each asynchronous operation completes.
        static void ProcessDnsInformation(IAsyncResult result)
        {
            string hostName = (string) result.AsyncState;
            hostNames.Add(hostName);
            try
            {
                // Get the results.
                IPHostEntry host = Dns.EndGetHostEntry(result);
                hostData.Add(host);
            }
            // Store the exception message.
            catch (SocketException e)
            {
                hostData.Add(e.Message);
            }
            finally
            {
                // Decrement the request counter in a thread-safe manner.
                Interlocked.Decrement(ref requestCounter);
            }
        }
    }
}

Top

时间: 2024-08-07 00:12:03

MSDN搬运 之 [使用 IAsyncResult 调用异步方法]的相关文章

MSDN搬运 之 [异步编程设计模式]

异步编程设计模式 异步操作通常用于执行完成时间可能较长的任务,如打开大文件.连接远程计算机或查询数据库.异步操作在主应用程序线程以外的线程中执行.应用程序调用方法异步执行某个操作时,应用程序可在异步方法执行其任务时继续执行. .NET Framework 为异步操作提供两种设计模式: 使用 IAsyncResult 对象的异步操作. 使用事件的异步操作. IAsyncResult 设计模式允许多种编程模型,但更加复杂不易学习,可提供大多数应用程序都不要求的灵活性.可能的话,类库设计者应使用事件驱

在同步中调用异步方法[.net 4.5]

using System; using System.Threading; using System.Threading.Tasks; namespace Microsoft.AspNet.Identity { internal static class AsyncHelper { private static readonly TaskFactory _myTaskFactory = new TaskFactory(CancellationToken.None, TaskCreationOpt

async await 同步方法调用异步方法死锁

同步方法调用异步方法.GetAwaiter().GetResult()计算函数超时,异步方法所有的回调操作都会期望返回到主线程. 所以会导致各种线程死锁.异步方法中使用ConfigureAwait(false)解决 1 public void Check(){ //todo 2 //验证userid和token是否匹配 3 var tUserId = UserIdAndTokenValidationAsync(userId, at.UserId); 4 //验证参数签名是否正确 5 Task<b

MSDN搬运 之 [基于事件的异步模式]

基于事件的异步模式概述 那些同时执行多项任务.但仍能响应用户交互的应用程序通常需要实施一种使用多线程的设计方案.System.Threading 命名空间提供了创建高性能多线程应用程序所必需的所有工具,但要想有效地使用这些工具,需要有丰富的使用多线程软件工程的经验.对于相对简单的多线程应用程序,BackgroundWorker 组件提供了一个简单的解决方案.对于更复杂的异步应用程序,请考虑实现一个符合基于事件的异步模式的类. 基于事件的异步模式具有多线程应用程序的优点,同时隐匿了多线程设计中固有

.net 同步方法调用异步方法假死

最近使用.net core 开发了一个项目,具体就不说了跟项目本身无关.先上一段代码 //示例代码 //前端调用方法 public string GetName() { return GetUserName().Result; } //服务端实现 public async Task<string> GetUserName() { var userModel=await GetUserModel(); return userModel.Name; } public async Task<U

MSDN搬运 之 [事件]

在发生其他类或对象关注的事情时,类或对象可通过事件通知它们.发送(或引发)事件的类称为“发行者”,接收(或处理)事件的类称为“订户”. 在典型的 C# Windows 窗体或 Web 应用程序中,可订阅由控件(如按钮和列表框)引发的事件.可使用 Visual C# 集成开发环境 (IDE) 来浏览控件发布的事件,选择要处理的事件.IDE 会自动添加空事件处理程序方法和订阅事件的代码.有关更多信息,请参见如何:订阅和取消订阅事件(C# 编程指南). 事件概述 事件具有以下特点: 发行者确定何时引发

MSDN搬运 之 [泛型 - 1]

泛型(C# 编程指南) 泛型是 2.0 版 C# 语言和公共语言运行库 (CLR) 中的一个新功能.泛型将类型参数的概念引入 .NET Framework,类型参数使得设计如下类和方法成为可能:这些类和方法将一个或多个类型的指定推迟到客户端代码声明并实例化该类或方法的时候.例如,通过使用泛型类型参数 T,您可以编写其他客户端代码能够使用的单个类,而不致引入运行时强制转换或装箱操作的成本或风险,如下所示: 复制 // Declare the generic class public class G

生产环境项目问题记录系列(二):同步方法调用异步方法

描述一下问题背景,公司部分项目还在使用老三层框架,存在跨库join的情况,在服务化的改造过程中,这些跨库join的老三层从都要被换成对应的服务接口. 目前有个项目通过sql访问了C端产品组的三张表,并且时跨库join,对方开发组要回收表的访问权,所有sql访问的都要改成接口访问. C端产品组提供的服务接口为.Net Core的Api接口,异步(.net core里HttpClient已经不再提供同步访问了).而这边调用的是一个老三层架构的定时任务,需要在同步方法里调用异步接口.当然你会问为什么不

C#同步调用异步方法

https://www.cnblogs.com/taro/p/7285126.html 使用Wait()和GetAwaiter().GetResult()方法实现异步方法同步执行 原文地址:https://www.cnblogs.com/xuelixue/p/10609837.html