• How to write an async method with out parameter?


    How to write an async method with out parameter?

    I want to write an async method with an out parameter, like this:

    public async void Method1()
    {
        int op;
        int result = await GetDataTaskAsync(out op);
    }

    How do I do this in GetDataTaskAsync?

    回答1

    You can't have async methods with ref or out parameters.

    Lucian Wischik explains why this is not possible on this MSDN thread: http://social.msdn.microsoft.com/Forums/en-US/d2f48a52-e35a-4948-844d-828a1a6deb74/why-async-methods-cannot-have-ref-or-out-parameters

    As for why async methods don't support out-by-reference parameters? (or ref parameters?) That's a limitation of the CLR. We chose to implement async methods in a similar way to iterator methods -- i.e. through the compiler transforming the method into a state-machine-object. The CLR has no safe way to store the address of an "out parameter" or "reference parameter" as a field of an object. The only way to have supported out-by-reference parameters would be if the async feature were done by a low-level CLR rewrite instead of a compiler-rewrite. We examined that approach, and it had a lot going for it, but it would ultimately have been so costly that it'd never have happened.

    A typical workaround for this situation is to have the async method return a Tuple instead. You could re-write your method as such:

    public async Task Method1()
    {
        var tuple = await GetDataTaskAsync();
        int op = tuple.Item1;
        int result = tuple.Item2;
    }
    
    public async Task<Tuple<int, int>> GetDataTaskAsync()
    {
        //...
        return new Tuple<int, int>(1, 2);
    }

    评论

    Far from being too complex, this could produce too many problem. Jon Skeet explained it very well here stackoverflow.com/questions/20868103/…

    Apr 21, 2015 at 13:21

    I think Named Tuples in C# 7 will be the perfect solution for this.
    – orad
    Mar 17, 2017 at 21:56

    回答2

    The C#7+ Solution is to use implicit tuple syntax.

        private async Task<(bool IsSuccess, IActionResult Result)> TryLogin(OpenIdConnectRequest request)
        { 
            return (true, BadRequest(new OpenIdErrorResponse
            {
                Error = OpenIdConnectConstants.Errors.AccessDenied,
                ErrorDescription = "Access token provided is not valid."
            }));
        }

    return result utilizes the method signature defined property names. e.g:

    var foo = await TryLogin(request);
    if (foo.IsSuccess)
         return foo.Result;

    回答3

    You cannot have ref or out parameters in async methods (as was already noted).

    This screams for some modelling in the data moving around:

    public class Data
    {
        public int Op {get; set;}
        public int Result {get; set;}
    }
    
    public async void Method1()
    {
        Data data = await GetDataTaskAsync();
        // use data.Op and data.Result from here on
    }
    
    public async Task<Data> GetDataTaskAsync()
    {
        var returnValue = new Data();
        // Fill up returnValue
        return returnValue;
    }

    You gain the ability to reuse your code more easily, plus it's way more readable than variables or tuples.

  • 相关阅读:
    ActiveMQ持久化消息
    JAXB XML到java object的转换
    Jackson JSON Processor
    Spring JDBC入门
    Quatz入门
    Jersey 入门与Javabean
    记安装ubuntu server和一些程序
    libevent 入门教程:Echo Server based on libevent(转)
    Linux Eclipse 运行Protobuf
    精神状态: Confused
  • 原文地址:https://www.cnblogs.com/chucklu/p/16444112.html
Copyright © 2020-2023  润新知