Commandline: async domain issue

Created on 22 Oct 2019  路  9Comments  路  Source: commandlineparser/commandline

I would like to work with dotnet async Main method, having the following signature:

static async Task Main(string[] args) {
        var parser = new Parser();
        var parserResult = parser.ParseArguments<Options>(args);
        var mainAsync = new MainAsync();
        parserResult.WithParsed<Options>(async options => await mainAsync.Run(options).ConfigureAwait());
}

Run is defined like:

    public async Task Run(Options options)
    {
        ...
    }

Problem is, my async methods behave strangely. They may work but can also simply terminate my program. It would seem I am doing something wrong, but I can't figure out what it is.

If I do this instead, there doesn't seem to be any problems, but I lose my async main method and some other stuff I have needs to be rewritten.

static void Main(string[] args) {
        var parser = new Parser();
        var parserResult = parser.ParseArguments<Options>(args);
        var mainAsync = new MainAsync();
        parserResult.WithParsed<Options>(options => mainAsync.Run(options).GetAwaiter().GetResult());
}

Why does the top-most Main fail in strange way and bottom one just works? Is CommandLineParser not async compatible?

question

All 9 comments

MapResult is supporting async/await but WithParsed is not supporting async/await.
See example in wiki for async/await with live demo.

Hey @moh-hassan, the linked example doesn't seem to work when the Task doesn't return anything.
Example

static async Task RunAndReturnExitCodeAsync(Options options)
{
   Console.WriteLine("Hello");
   await Task.Delay(200); //simulate async method
   Console.WriteLine("World");
}

Calling it in Main() as:

Console.WriteLine("Start");
var result = Parser.Default.ParseArguments<Options>(args)
     .MapResult(async options => await RunAndReturnExitCodeAsync(options), _ => Task.FromResult(1));
Console.WriteLine("Finish");

The Thread is not awaited in the RunAndReturnExitCodeAsync function.
Am I doing something wrong?

I think result.Wait() solves the problem, and this would be the correct way of doing it?

@anas2204
MapResult is Func not Action, so you should use Task<T>. Use return value.
In v 2.8 you can use Task with WithParsedAsync.
Avoid using Wait in async/await context.

@moh-hassan Thanks for the update to the library!
I tried the example given here, and it seems to exit after printing "Before Task".

Isn't calling ".Result" or ".Wait()" same in the context of async/await?

If you tried the demo here, you get the result as expected:
output:

Starting async/await method
Before async/await
UserId=root
After async/await

Can you confirm this result?

Isn't calling ".Result" or ".Wait()" same in the context of async/await?

Wait() cause Deadlocks in your application.

Can you confirm this result?

For me, running the example on a .NET Core 3.1 Console application, I get this output:

Starting async/await method
Before async/await

Wait() cause Deadlocks in your application.

Is there a case for Deadlock in a Console application?

Also, in the sample you linked, shouldn't the Main() also have "async"?

shouldn't the Main() also have "async"?

Yes, it should have since c#7.1
I modified dotnetfiddle demo to run in NetCore 3.1 and it's working fine and also in vs 2019.
Note async in Main and await for MapResult and WithParsedAsync using a method group for lambda expression.

public static async Task<int> Main(string[] args)
{       
      int ret =await Parser.Default.ParseArguments<Options>(args)
            .MapResult( RunAndReturnExitCodeAsync,   _ => Task.FromResult(1));
    Console.WriteLine($"retCode={ret}");
    return ret;
}

Demo MapResult
WithParsedAsync:

  public static async  Task Main(string[] args)
        {           
            await Parser.Default.ParseArguments<Options>(args)
                .WithParsedAsync(RunAsync);
        }

Demo WithParsedAsync

Thanks for the prompt reply @moh-hassan, this works great!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Rohansi picture Rohansi  路  6Comments

timotei picture timotei  路  4Comments

Silverwing1983 picture Silverwing1983  路  4Comments

IB38 picture IB38  路  4Comments

Eason-Lian picture Eason-Lian  路  3Comments