异步编程模式和进度报告

在现代应用程序开发中,异步编程已成为处理并发操作的一种高效方式。它不仅提高了应用程序的响应性,还简化了代码的编写和维护。本文将探讨如何使用.NET的异步编程模式(Task-based Asynchronous Pattern,简称TAP)和进度报告接口(IProgress)来创建一个异步的Ping工具。

TAP和IProgress简介

.NET的异步编程模式(TAP)定义了异步函数应该实现的接口。它包括两个部分:编译器的扩展和基于任务的异步模式。编译器扩展通过引入async和await关键字来实现,而TAP则定义了异步函数的签名。

异步函数的签名如下:

public Task<TResult> DoWorkAsync(… parameters, CancellationToken cancellationToken, IProgress<T> progress);

其中,方法返回一个Task,方法名后附加了Async,方法接受一个CancellationToken和一个IProgress<T>。

IProgress<T>和Progress<T>

.NET Framework 4.5引入了IProgress<T>接口,它包含一个Report方法,用于异步方法报告进度。Progress<T>类是IProgress<T>的一个简单实现,它提供了一个接受Action<T>的构造函数和一个ProgressChanged事件,用于注册进度更新的回调。

使用Progress<T>实现异步Ping

为了实现异步Ping,首先需要一个类来报告Ping的进度。这个类是一个容器,用于存储Ping状态的各种信息。

public class PingResult { public IPAddress Address { get; private set; } public int PingsTotal { get; private set; } public int PingsSuccessful { get; private set; } public TimeSpan AverageTime { get; private set; } public TimeSpan LastTime { get; private set; } public IPStatus LastStatus { get; private set; } public PingResult(IPAddress address) { Address = address; LastStatus = IPStatus.Unknown; } internal void AddResult(PingReply res) { ... } }

PingResult类包含了Ping操作的各种状态信息,如地址、总Ping次数、成功Ping次数、平均时间、最后一次Ping的时间和状态等。AddResult方法将由Ping方法调用,以累积信息到AverageTime、PingsTotal等属性中。

Ping方法

有了PingResult类,就可以创建一个异步Ping方法了。这个方法是对System.Net.NetworkInformation.Ping功能的包装。

public static async Task ContinuousPingAsync( IPAddress address, int timeout, int delayBetweenPings, IProgress<PingResult> progress, CancellationToken cancellationToken) { var ping = new System.Net.NetworkInformation.Ping(); var result = new PingResult(address); while (!cancellationToken.IsCancellationRequested) { var res = await ping.SendPingAsync(address, timeout).ConfigureAwait(false); result.AddResult(res); progress.Report(result); await Task.Delay(delayBetweenPings).ConfigureAwait(false); } }

这个方法是一个静态方法,所有状态(result和ping)都隐藏在内部。方法返回一个Task,以便调用者可以处理运行中的计算。IProgress<PingResult>对象用于报告Ping状态。方法可以使用CancellationToken来取消。

WPF示例应用程序

源代码还包括一个简单的WPF MVVM应用程序示例。可以输入要Ping的计算机地址。DNS解析和Ping都是使用本文的方法异步完成的。

使用代码

namespace Network { public static class Ping { public static IPAddress ResolveAddress(string hostNameOrAddress) { ... } public static async Task<IPAddress> ResolveAddressAsync(string hostNameOrAddress) { ... } public static async Task ContinuousPingAsync( IPAddress address, int timeout, int delayBetweenPings, IProgress<PingResult> progress, CancellationToken cancellationToken) { ... } } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485