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

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

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

在异步操作完成之前使用 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);
}
}
}
}

使用 IAsyncResult 调用异步方法的更多相关文章

  1. 又踩.NET Core的坑:在同步方法中调用异步方法Wait时发生死锁(deadlock)

    之前在将 Memcached 客户端 EnyimMemcached 迁移 .NET Core 时被这个“坑”坑的刻骨铭心(详见以下链接),当时以为只是在构造函数中调用异步方法(注:这里的异步方法都是指 ...

  2. 一码阻塞,万码等待:ASP.NET Core 同步方法调用异步方法“死锁”的真相

    在我们 2015 年开始的从 .NET Framework 向 .NET Core 迁移的工程中,遇到的最大的坑就是标题中所说的--同步方法中调用异步方法发生"死锁".虽然在 .N ...

  3. 同步调用异步方法how-would-i-run-an-async-taskt-method-synchronously

    同步调用异步方法帮助类: public static class AsyncHelpers { /// <summary> /// Execute's an async Task<T ...

  4. JavaScript日历控件开发 C# 读取 appconfig文件配置数据库连接字符串,和配置文件 List<T>.ForEach 调用异步方法的意外 ef 增加或者更新的习惯思维 asp.net core导入excel 一个二级联动

    JavaScript日历控件开发   概述 在开篇之前,先附上日历的代码地址和演示地址,代码是本文要分析的代码,演示效果是本文要实现的效果代码地址:https://github.com/aspwebc ...

  5. ABP .Net Core 调用异步方法抛异常A second operation started on this context before a previous asynchronous operation completed

    1.  问题描述 最近使用ABP .Net Core框架做一个微信开发,同时采用了一个微信开发框架集成到ABP,在微信用户关注的推送事件里调用了一个async 方法,由于没有返回值,也没做任何处理,本 ...

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

    同步方法调用异步方法.GetAwaiter().GetResult()计算函数超时,异步方法所有的回调操作都会期望返回到主线程. 所以会导致各种线程死锁.异步方法中使用ConfigureAwait(f ...

  7. .NET中如何在同步代码块中调用异步方法

    更新记录 本文迁移自Panda666原博客,原发布时间:2021年7月2日. 在同步代码块中调用异步方法,方法有很多. 一.对于有返回值的Task 在同步代码块中直接访问 Task 的 Result ...

  8. C#-等待异步函数执行结果-将调用异步方法的函数变成非异步执行

    先来简单了解一下async.await 使用async await 的前提条件:需要C# 5.0以上版本 .NET Framework 4.5以上 Visual Studio 2012以上. asyn ...

  9. List<T>.ForEach 调用异步方法的意外

    有这么个异步方法 private static async Task<int> Compute(int s) { return await Task<int>.Run(() = ...

随机推荐

  1. view 的继承关系

    view 的继承关系 如果一个view 有多个子view. 甚至是多成次的 子view. 只需要把第一级别的view(父view) 授权给用户,就可以访问view了,子view 不需要授权.

  2. 全面学习ORACLE Scheduler特性(10)管理Chains

    5.2  管理Chains 5.2.1  修改Chains属性 基本上碰到修改CHAIN属性的机率不会太大,因此确实没啥可修改的,对于CHAIN对象来说,能够修改的属性只有两个:evaluation_ ...

  3. 【ZT】在微信上有哪些高情商的说话方式 | M周刊(听语音需要60秒,看文字只需10秒)

    https://baijiahao.baidu.com/s?id=1590547145580792217&wfr=spider&for=pc https://yuedu.baidu.c ...

  4. Android基础夯实--重温动画(一)之Tween Animation

    心灵鸡汤:真正成功的人生,不在于成就的大小,而在于你是否努力地去实现自我,喊出自己的声音,走出属于自己的道路. 摘要 不积跬步,无以至千里:不积小流,无以成江海.学习任何东西我们都离不开扎实的基础知识 ...

  5. 介绍Git的17条基本用法

    本文将介绍Git的17条基本用法.本文选自<Python全栈开发实践入门>. 1.初始化Git仓库 Git仓库分为两种类型:一种是存放在服务器上面的裸仓库,里面没有保存文件,只是存放.gi ...

  6. Linux 学习(四)

    搭建jdk 安装jdk操作: 1.光驱挂载:mount /dev/cdrom /mnt 2.拷贝安装包至其他文件夹(如home目录下) 3.执行安装包(bin包:./包名) 4.配置环境变量:打开文件 ...

  7. 本地调试hbase

    需求说明 如果要本地调试Hbase程序,那么可以用本地连接集群的方式 配置文件 在maven里,配置文件cluster.properties放在target/classes里 cluster.prop ...

  8. Java 基础入门随笔(4) JavaSE版——程序流程控制

    上一节对于运算符有了大致的了解,这一节针对程序流程控制进行复习!程序流程控制包括顺序结构.判断结构(if).选择结构(switch).循环结构. 1.判断结构 ①if语句的第一种格式:        ...

  9. 使用CAShapeLayer的path属性与UIBezierPath画出扫描框

    1.CAShapeLayer CAShapeLayer具有path属性,(是CGPath对象),可以使用这个属性与UIBezierPath画出想要的图形.该子类根据其fill color和stroke ...

  10. 搭建jQuery开发环境

    每个版本又分为一下两种:开发版和生产版: 版本 大小/KB 描述jquery-1.x.js 约288 开发版,完整无压缩,多用于学习,开发和测试jquery-2.x.js 约251 开发版,完整无压缩 ...