【问题标题】:Can the C# compiler distinguish between I/O bound and computational tasks?C# 编译器可以区分 I/O 绑定任务和计算任务吗?
【发布时间】:2016-04-26 00:39:17
【问题描述】:

考虑如下代码的 sn-p:

public async Task<Bitmap> DownloadDataAndRenderImageAsync(
    CancellationToken cancellationToken)
{
    var imageData = await DownloadImageDataAsync(cancellationToken);
    return await RenderAsync(imageData, cancellationToken);
}

此方法中的第一步是 I/O 绑定工作,第二步是计算。

当我们依赖编译器为这个异步操作生成正确的基于任务的代码时,编译器会做什么?

具体来说,它是否知道第一个是 I/O 绑定的,所以它必须使用 TaskCompletionSource&lt;T&gt; 类,这样线程和任务之间就没有关联,而对于第二个,它可以使用任何RunStartNewStart 等方法在线程池线程上调度任务?

【问题讨论】:

    标签: c# .net asynchronous async-await


    【解决方案1】:

    没有。在您给出的示例中,编译器将仅将TaskCompletionSource&lt;T&gt;(间接)用于整个异步操作(DownloadDataAndRenderImageAsync)。由调用的两个方法决定它们将如何返回相关任务。

    也许DownloadImageDataAsync 本身就是一个async 方法,它委托给更多的异步I/O。也许RenderAsync 打电话给Task.Run。这些都是编译器在编译DownloadDataAndRenderImageAsync时完全不关心的实现细节

    【讨论】:

      【解决方案2】:

      当我们依赖编译器为这个异步操作生成正确的基于任务的代码时,编译器会做什么?

      在您给编译器的示例中,您知道 DownloadImageDataAsync 和 RenderAsync 是返回可等待对象的方法。 Awaitables 是可以 (1) 查询完成的对象,以及 (2) 有一个注册到它们完成的延续。编译器生成代码来检测返回的可等待对象是否已完成,如果未完成,则将方法的其余部分标记为可等待对象的完成。

      具体来说,它是否知道第一个是 I/O bound

      不。它知道它返回了可以等待的东西。

      所以它必须使用 TaskCompletionSource 类,这样线程和任务之间就没有关联

      如果您关心完成逻辑的细节,您有责任确保等待发生的上下文是正确的上下文。如果你不在乎,你会得到一个合适的默认上下文。

      对于第二个,它可以使用 Run 或 StartNew 或 Start 等任何方法将任务安排在线程池线程上?

      编译器不会做任何这样的事情。编译器生成代码来检查返回的可等待对象是否完成,如果没有,则标记可等待对象的完成。 awaitable 的工作原理是被调用者的责任,而不是编译器!

      【讨论】:

        【解决方案3】:

        编译器和运行时都不知道。事实上,整个术语“IO bound”的定义很模糊。任何操作系统都称为 IO 吗?睡眠或计时是 IO 吗?!

        如果你必须问这个问题,你可能会对任务有一些误解,因为通常没有必要知道这一点。

        也许认为 await 启动任务是常见的错误?它等待现有任务完成。 DownloadImageDataAsyncRenderAsync 决定如何以及何时完成该任务。所以他们决定是使用 CPU 还是执行 IO。

        DownloadImageDataAsyncRenderAsync 交给你一个你不知道里面有什么并且你不需要知道的任务时。

        【讨论】:

        • Is any OS call an IO?! Is sleeping or timing an IO?! 是的。具有side effects 的函数不是pure,出于问题的意图和目的,IO 似乎与纯度混为一谈。
        • @cat 纯 != 无 IO。即使 IO 被精确定义,并且您的定义没有被普遍接受,问题仍然是:什么是 IO-bound?没有什么是 100% IO。这么模糊的名词。
        • @usr:当然,一旦你足够严格地定义它以使问题开始有意义,答案是:决定这个问题等同于解决停机问题。 (这几乎是对“编译器能否区分 XYZ”形式的所有问题的答案。)
        猜你喜欢
        • 2020-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-03
        • 2021-03-08
        • 2021-05-22
        • 2015-05-30
        相关资源
        最近更新 更多