Commandline: In WithParsed () method, I cann't await async in lambda .

Created on 22 Sep 2018  路  3Comments  路  Source: commandlineparser/commandline

The call await new Command(x).Execute() which is called from within await async lambda, does not wait for the task completion and the next line is executed immediately.

The next code isn't working fine:

   static void Main(string[] args)
    {
      RunOptions(args);
    }

   static void RunOptions(string[] args)
    {
    var parser= new Parser();
      var result = parser.ParseArguments<Options>(args);
         //note async x in lambda
        result.WithParsed(async x => {               
            await new Command(x).Execute();
        });          
  }

I think it is expected because it's against the principle use async all the way up

How to use async/await in result.WithParsed
I want to re-write the code to use asyn Main() in C#7.1

  static async Task Main(string[] args)
    {
    await  RunOptions(args);
    }

   static async Task RunOptions(string[] args)
    {
        //rewrite the code using result.WithParsed(...)
       // or WithParsed don't support async/await
   }

I find this example for MapResult , but i need to use .WithParsed`

Most helpful comment

Hi @nemec , Thanks for your solution and I accept it.
I tried it, and did a minor modification in your code , and it's working fine.

            await result.MapResult(async 
               x =>
                     {                       
                         await new Command(x).Execute();
                     },
                 errors => Task.FromResult(0)
      );

MapResult is the BEST. :)

All 3 comments

Hi Mohamed, why can't you use MapResult? WithParsed is designed intentionally to take an Action<TOpt>, which as you noted cannot be awaited. MapResult is designed explicitly with 'return values' in mind, which is why it takes a Func<TOpt, TResult>.

Assuming you don't want to use the WithNotParsed method to handle errors, you should be able to replace your last line above with something like the following (not tested):

result.MapResult<Options>(async x => 
{
    return await new Command(x).Execute();
},
errors => Task.FromResult<TypeReturnedFromExecute>(null));

Note we just return a no-op in the error path. No big deal, it will have the same effect as not handling the errors at all.

Hi @nemec , Thanks for your solution and I accept it.
I tried it, and did a minor modification in your code , and it's working fine.

            await result.MapResult(async 
               x =>
                     {                       
                         await new Command(x).Execute();
                     },
                 errors => Task.FromResult(0)
      );

MapResult is the BEST. :)

Great! I am glad it worked out for you.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ericnewton76 picture ericnewton76  路  3Comments

SeanoNET picture SeanoNET  路  4Comments

timotei picture timotei  路  4Comments

ericnewton76 picture ericnewton76  路  4Comments

IB38 picture IB38  路  4Comments