I'm using it CommandLineParser from and async Task Main method.
I would like to use verbs, so I would use the recommended syntax:
CommandLine.Parser.Default.ParseArguments<Options1, Options2, Options3>(args)
.MapResult(
(Options1opts) => Method1(opts),
(Options2opts) => Method2(opts),
(Options3opts) => Method2(opts),
errs => 1);
But in my case, the methods are async. Howo do I use the MapResult in this scenario?
The same problem occurs with the WithParsed methods.
Thanks!
Can you use await?
.MapResult(
(Options1opts) => await Method1(opts),
(Options2opts) => await Method2(opts),
@ericnewton76 It doesn't work, this doesn't await the method. I think it's happening what is explained here:
Take a look to the part when he says "With this function, if I then run the following code:".
It looks only by using await in the lambdas, won't work. The MapResult method isn't returning a Task you can await it, and the Main method will continue its execution before anything inside MapResult is executed.
@SuperJMN since your methods are async, you also need to await the result from the parser:
await CommandLine.Parser.Default.ParseArguments [...]
Taking the timer example you posted, here is how I reworked it to support an async Task Main method - you can probably do the same for your methods, as needed.
async Task Main()
{
Func<Task> t = async () =>
{
await Task.Delay(1000);
};
double secs = await Time(t); // Note we're awaiting the result of the timer method, to return control back to the entry point
Console.WriteLine("Seconds: {0:F7}", secs);
}
public static async Task<double> Time(Func<Task> action, int iters = 10)
{
var sw = Stopwatch.StartNew();
for (int i = 0; i < iters; i++) await action();
return sw.Elapsed.TotalSeconds / iters;
}
@nemec The result from the parser can be awaited only if it returns a Task, which it doesn't. An overload would help here.
@shravan2x I'm not sure I understand. OP's methods return tasks already so there's no issue. Here is a full example of what I'm talking about.
async Task Main()
{
var args = "a --name tim".Split();
await CommandLine.Parser.Default.ParseArguments<Options1, Options2, Options3>(args)
.MapResult(
(Options1 opts) => Method1(opts),
(Options2 opts) => Method2(opts),
(Options3 opts) => Method3(opts),
errs => Task.FromResult(0));
}
public async Task<int> Method1(Options1 opt)
{
Console.WriteLine("Method1 " + opt.Name);
await Task.Delay(TimeSpan.FromSeconds(1));
return 1;
}
public async Task<int> Method2(Options2 opt)
{
Console.WriteLine("Method2");
await Task.Delay(TimeSpan.FromSeconds(1));
return 2;
}
public async Task<int> Method3(Options3 opt)
{
Console.WriteLine("Method3");
await Task.Delay(TimeSpan.FromSeconds(1));
return 3;
}
[Verb("a")]
public class Options1
{
[Option('n', "name")]
public string Name { get; set; }
}
[Verb("b")]
public class Options2
{
}
[Verb("c")]
public class Options3
{
}
This issue should be closed. Works perfectly with async/await as long as you're well aware of how async/await works.
Agreed, however I like to give the original submitter time to respond in case they have other problems with the solution.
@nemec I hadn't noticed that MapResult returns a generic TResult. Your example works.
Thanks for the info! Now I know how to proceed :)
Most helpful comment
@shravan2x I'm not sure I understand. OP's methods return tasks already so there's no issue. Here is a full example of what I'm talking about.