什么是使用async-await的方法的async-await-free等价物?

时间:2018-06-15 10:12:58

标签: c# asynchronous async-await

我试图理解究竟是什么,在C#中,使用async await的方法正在做什么。

考虑以下两个例子:

static async Task<byte[]> MyReadAsync1(Stream source)
{
    var result = new byte[1024];
    int readBytes = 0;

    while (readBytes != result.Length)
    {
        int singleRead = await source.ReadAsync(result, readBytes, result.Length - readBytes);
        if (singleRead == 0)
            break;
        readBytes += singleRead;
    }

    if (readBytes == result.Length)
        return result;
    return result.Take(readBytes).ToArray();
}

static Task<byte[]> MyReadAsync2(Stream source)
{
    return Task.Run(() =>
    {
        var result = new byte[1024];
        int readBytes = 0;

        while (readBytes != result.Length)
        {
            int singleRead;
            try
            {
                singleRead = source.ReadAsync(result, readBytes, result.Length - readBytes).Result;
            }
            catch (AggregateException e)
            {
                ExceptionDispatchInfo.Capture(e.InnerException).Throw();
            }

            if (singleRead == 0)
                break;
            readBytes += singleRead;
        }

        if (readBytes == result.Length)
            return result;
        return result.Take(readBytes).ToArray();
    });
}

我的问题是:这两种方法是否相同?

如果我执行它们,它看起来就像是。它们都没有阻塞调用线程。就我所知,他们正在做同样的事情,即使在抛出任何异常的情况下也是如此。

如果它们真的相同,编译器是否会产生相同的代码?这是否意味着async await除了保存我输入一些样板代码,启动一个任务并解开AggregateExceptions之外什么也不做呢?

如果存在差异,究竟是什么,如果没有async await,是否可以实现完全相同的行为?

注意:我已经看到问题What is the purpose of “return await” in C#?,我理解那里给出的答案。但这只涉及一个单一的返回声明的情况,而我的问题意味着更一般。

我没有质疑async await的目的,我只是想详细了解它。

更新

possible duplicate没有回答我的问题。该问题仅涵盖一行代码,比较.Resultawait。在我的问题中,我有很多额外的代码,这些代码是&#34;混合&#34;使用异步代码并在MyReadAsync2方法中将整个执行包装在Task.Run中。我无法看到另一个问题是如何解决这些额外问题的。

1 个答案:

答案 0 :(得分:1)

粗略地说,如果你想写一个&#34; await免费&#34;代码的版本,您在与Result大致相同的位置使用ContinueWith,而不是使用await(如上所述,将阻止 a < / em> thread并可能导致死锁。)

当然,这忽略了同步上下文机制,例如,如果这是调用原始方法的上下文,则可以使您的代码在UI线程上运行。您还会发现(如果您有多个await)您的嵌套级别发疯并且您无法轻松使用某些构造(例如,尝试在ContinueWith内部执行async一个循环,然后尝试使用await 1,2 )编写等效项。

async / async给你的很多机器,你不必经常偷看幕后。但是,如果您愿意,您可以尝试编译一些基于async的代码,然后通过一个不支持await的反编译器运行它,或者可以选择不尝试反向工程async方法。

1 在大多数情况下,并非简单的循环只是调用ContinueWith.data\maven\configjar\configjar.log代码的典型示例。

2 请注意,在此示例中,循环的每次迭代仅在前一个等待完成时开始 - 因此您必须将循环上下文传递给您的任何方法#39;重新转到The system cannot find the path specified.来电。