代码之家  ›  专栏  ›  技术社区  ›  David Thielen

返回任务与使用等待

  •  0
  • David Thielen  · 技术社区  · 2 年前

    我正在努力跟随 the guidance in this blog about not using await when not needed 。首先,如果 using { ... } 涉及,则是-使用等待。

    好的,那么对于下面的代码,为什么 DoItTask() 不工作?如果方法中没有使用wait,那么返回Task而不使用wait是否仅有效?

        private static async Task<string> ReadOne()
        {
            return await readerOne.ReadAsync();
        }
    
        private static async Task<string> ReadTwo()
        {
            return await readerTwo.ReadAsync();
        }
    
        private static async Task<string> ReadThree()
        {
            return await readerOne.ReadAsync();
        }
    
        private static async Task<string> ReadCombinedAsync(string one, string two, string three)
        {
            return await reader.CombineAsync(one, two, three);
        }
    
        private static Task<string> ReadCombinedTask(string one, string two, string three)
        {
            return reader.CombineAsync(one, two, three);
        }
    
        private static async Task<string> DoItAwait()
        {
            string one = await ReadOne();
            string two = await ReadOne();
            string three = await ReadOne();
    
            return await ReadCombinedAsync(one, two, three);
        }
    
        private static Task<string> DoItTask()
        {
            string one = await ReadOne();
            string two = await ReadOne();
            string three = await ReadOne();
    
            return ReadCombinedAsync(one, two, three);
        }
    

    ps- I initially asked this question with a very sloppy example. 对此深表歉意。

    1 回复  |  直到 2 年前
        1
  •  2
  •   Julian    2 年前

    以下内容不起作用,因为您无法使用 await 没有 async 。这些关键字 总是 在使用任务并行库(TPL)时一起使用:

    private static Task<string> DoItTask()
    {
        //problem: method is not async - compiler error
        string one = await ReadOne(); 
        string two = await ReadOne();
        string three = await ReadOne();
    
        // OK, because method is not async
        return ReadCombinedAsync(one, two, three);
    }
    

    的异步方法 async Task 签名在引擎盖下创建一个状态机,然后执行异步操作而不阻塞调用线程。当任何正在执行的任务尚未完成时,调用方法将挂起。在异步方法内部,您只能 等候 其他异步任务或启动任务而不返回它们。

    当您使用同步方法时,情况就不同了。在那里,Task实际上可以直接返回:

    public Task GetSomeTaskAsync()
    {
        return SomethingElseAsync();
    }
    
    public async Task AwaitTaskAsync()
    {
        await GetSomeTaskAsync();
    }
    

    只有当您真的可以传递任务而不执行与该操作相关的任何其他操作时,这才有用,这样您就可以节省一些资源,因为的状态机 异步任务 产生一些开销。不利的一面是,当出现异常时,您将丢失一些堆栈跟踪信息。

    您可以在此处找到更多有用信息: Why use async and return await, when you can return Task directly?

    回到您的场景,这里只有两个选项:

    private static async Task<string> DoItTask()
    {
        string one = await ReadOne();
        string two = await ReadOne();
        string three = await ReadOne();
    
        return await ReadCombinedAsync(one, two, three);
    }
    

    private static async Task<Task<string>> DoItTask()
    {
        string one = await ReadOne();
        string two = await ReadOne();
        string three = await ReadOne();
    
        return ReadCombinedAsync(one, two, three);
    }
    

    后者实际上返回一个 Task<string> 作为的结果 异步任务

    注意:我不建议这样做,这会让其他开发人员非常困惑,因为这是出乎意料的。应尽可能等待任务。如果返回Task,则在发生异常时,将丢失堆栈跟踪中调用堆栈的部分内容。如果在许多地方执行此操作,尤其是在像这样将Tasks包装在Tasks中时,调试会非常麻烦。