c# - 如何从头开始实现异步 I/O 绑定(bind)操作?

标签 c# asynchronous async-await

我试图了解如何以及何时使用async 编程和I/O 绑定(bind)操作,但我不理解它们。我想从头开始实现它们。我该怎么做?

考虑下面的同步示例:

private void DownloadBigImage() {
    var url = "https://cosmos-magazine.imgix.net/file/spina/photo/14402/180322-Steve-Full.jpg";
    new WebClient().DownloadFile(url, "image.jpg");
}

如何通过仅使用普通同步方法 DownloadBigImage 而不使用 Task.Run 来实现 async 版本 因为那将使用线程池中的线程仅用于等待 - 这只是浪费!

另外不要使用已经是async的特殊方法!这就是这个问题的目的:如何在不依赖已经异步的方法的情况下自己制作它?所以,不要这样的事情:

await new WebClient().DownloadFileTaskAsync(url, "image.jpg");

在这方面非常缺乏可用的示例和文档。我只找到了这个: https://learn.microsoft.com/en-us/dotnet/standard/async-in-depth 其中说:

The call to GetStringAsync() calls through lower-level .NET libraries (perhaps calling other async methods) until it reaches a P/Invoke interop call into a native networking library. The native library may subsequently call into a System API call (such as write() to a socket on Linux). A task object will be created at the native/managed boundary, possibly using TaskCompletionSource. The task object will be passed up through the layers, possibly operated on or directly returned, eventually returned to the initial caller.

基本上我必须使用“P/Invoke interop 调用到本地网络库”......但如何?

最佳答案

这是一个很好的问题,在大多数关于 C# 和异步的文本中确实没有很好地解释。

我搜索了很长时间,认为我可以而且应该实现我自己的异步 I/O 方法。如果我使用的方法/库没有异步方法,我想我应该以某种方式将这些函数包装在使它们异步的代码中。事实证明,这对大多数程序员来说并不是真正可行的。是的,您可以使用 Thread.Start(() => {...}) 生成一个新线程,这确实会使您的代码异步,但它也会创建一个新线程,这是一项昂贵的开销用于异步操作。它当然可以释放您的 UI 线程以确保您的应用程序保持响应,但它不会像 HttpClient.GetAsync() 那样创建真正的异步操作是真正的异步操作。

这是因为 .net 库中的异步方法使用称为“.NET 中的标准 P/Invoke 异步 I/O 系统”的东西来调用低级操作系统代码,在执行出站 IO 时不需要专用 CPU 线程(网络或存储)。它实际上并没有将线程专门用于它的工作,而是在它完成它的工作时向 .net 运行时发出信号。

我不熟悉细节,但这些知识足以让我从尝试实现异步 I/O 中解脱出来,并让我专注于使用 .net 库中已有的异步方法(例如 HttpClient.GetAsync( )).可以找到更多有趣的信息here (Microsoft async deep dive)和一个不错的description by Stephen Cleary here

关于c# - 如何从头开始实现异步 I/O 绑定(bind)操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50985593/

相关文章:

c# - 从导航堆栈中删除时从 UIViewController 中删除数据

c# - await AsyncMethod() 与 await await Task.Factory.StartNew<TResult>(AsyncMethod)

c# - 如何在 .NET 中测试并发场景?

xamarin - 将返回无效的 View 生命周期方法(如 ViewDidLoad/OnCreate async)标记为不好的做法吗?

c# - 如何在异步方法中启动未等待的后台任务?

c# - 将十进制(用户字符串)转换为带有 0x 前缀的十六进制

c# - 查询 IEnumerable 中具有相似属性且在特定时间阈值内的对象

c# - 需要帮助将 laravel Crypt 转换为 C#

c# - 使用异步 Controller 操作调用现有同步方法

react-native - 如何将访问 token 从 API 存储到异步存储