更新 - 2021 年 11 月 1 日
大多数原始技术在 .NET Framework 4.7 及更高版本以及 .NET Core(包括 .NET 5 及更高版本)中作为开箱即用的方法提供。目前 .NET 6 已在生产中得到支持,目前对 .NET 的长期支持,两周后即可获得完整的 RTM。
await socket.ConnectAsync(someIp,somePort);
await socket.Send(msg, SocketFlags.None);
类支持通过可选的 CancellationToken 参数取消。
-
对于基于 Socket 的高性能代码,Pipes were introduced 允许通过重用从一个处理步骤传递到下一个处理步骤的内存缓冲区,以最少的分配处理任意消息大小。这节省了内存和在缓冲区之间复制数据所需的时间。
-
WebClient 完全被 HttpClient 取代。事实上,WebClient 和 HttpWebRequest 类现在只是 HttpClient 的兼容性包装器。 HttpClient 是线程安全和异步的,使用套接字和管道提供比 WebClient 更好的性能:
HttpClient _client=new HttpClient(...);
...
async Task<string> GetThatPage(string someUrl)
{
var page=await _client.GetStringAsync(someUrl);
....
}
在 .NET 6 中,Parallel.ForEachAsync 使得同时发出多个异步请求变得微不足道:
var urls=new List<string>();
...
await Parallel.ForEach(urls,async url=>{
var page=_client.GetStringAsync(url);
var fileName=CalculateNameFrom(url);
await File.WrileAllTextAsync(fileName,page);
});
.NET (Core) 中的默认编码是 UTF8。
var reply=await ping.SendPingAsync(someIP);
原始答案 (2012)
Stephen Toub 在“Awaiting Socket Operations”中讨论了 .NET 4.5 的这个主题。通过一些工作,您可以对 .NET 4 使用相同的技术。
您可以将任务并行库用于simplify asynchronous calls,而不是使用回调。使用 TPL,您可以将所有套接字操作和回调转换为调用操作并处理结果的任务。
使用 ContinueWith 等方法可以非常轻松地组合任务,以便仅在第一个任务完成时执行链中的下一个任务。
使用线程池中的线程执行任务,因此您不必担心线程。
TPL 已经提供了一种从 BeginXXX/EndXXX 函数对或 IAsyncResult 对象创建任务的方法。如果您的套接字库提供了这些,您可以立即开始使用任务。
要处理事件,您可以使用任务并行库中的 TaskCompletionSource 创建一个任务,该任务将在您调用套接字方法时启动,并仅在引发相应事件时完成。该技术在“Tasks and the Event-based Asynchronous Pattern”中有所描述
ParallelExtensionsExtras 库使用这种技术为WebClient, SmtpClient and Ping 提供异步方法版本。
使用“任务和 EAP”中的代码,您可以为您的 Socket 类编写扩展方法,如下所示:
public static Task ConnectTask( this Socket socket, object address)
{
var tcs = CreateSource(address);
socket.ConnectCompleted +=
(sender, e) => TransferCompletion(tcs, e, () => e.Result, null);
socket.ConnectAsync(address, tcs);
return tcs.Task;
}
并像这样使用它:
var connectTask=mySocket.ConnectTask(myaddress);
connectTask.ContinueWith(t=> { ... });
在 .NET 4.5 中事情变得更加容易。 async/await 关键字允许您取消 ContinueWith 调用并编写看起来与其同步版本非常相似的代码。您可以检查“Awaiting Socket Operations”以获得专门针对 Sockets 的扩展。