290

I've got this code:

private async void ContextMenuForGroupRightTapped(object sender, RightTappedRoutedEventArgs args)
{
    CheckBox ckbx = null;
    if (sender is CheckBox)
    {
        ckbx = sender as CheckBox;
    }
    if (null == ckbx)
    {
        return;
    }
    string groupName = ckbx.Content.ToString();

    var contextMenu = new PopupMenu();

    // Add a command to edit the current Group
    contextMenu.Commands.Add(new UICommand("Edit this Group", (contextMenuCmd) =>
    {
        Frame.Navigate(typeof(LocationGroupCreator), groupName);
    }));

    // Add a command to delete the current Group
    contextMenu.Commands.Add(new UICommand("Delete this Group", (contextMenuCmd) =>
    {
        SQLiteUtils slu = new SQLiteUtils();
        slu.DeleteGroupAsync(groupName); // this line raises Resharper's hackles, but appending await raises err msg. Where should the "async" be?
    }));

    // Show the context menu at the position the image was right-clicked
    await contextMenu.ShowAsync(args.GetPosition(this));
}

...that Resharper's inspection complained about with, "Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call" (on the line with the comment).

And so, I prepended an "await" to it but, of course, I then need to add an "async" somewhere, too - but where?

B. Clay Shannon-B. Crow Raven
  • 8,547
  • 144
  • 472
  • 862
  • 1
    https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions#async-lambdas – samus May 29 '18 at 18:57
  • 1
    @samsara: Nice, I wonder when they finally documented that somewhere outside the C# spec. IIRC, no documentation existed at the time this question was asked. – BoltClock Sep 18 '18 at 17:34

3 Answers3

453

To mark a lambda async, simply prepend async before its argument list:

// Add a command to delete the current Group
contextMenu.Commands.Add(new UICommand("Delete this Group", async (contextMenuCmd) =>
{
    SQLiteUtils slu = new SQLiteUtils();
    await slu.DeleteGroupAsync(groupName);
}));
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • 2
    I get an error from Visual Studio that Async void methods are not supported. – Kevin Burton Dec 11 '19 at 16:01
  • 1
    @Kevin Burton: Yeah, async voids are usually only limited to event handlers. The API you're using is either not async or has an async version expecting an async Task lambda instead. – BoltClock Dec 17 '19 at 17:16
  • Can anyone help me out by giving some link to explanation how such async lambdas would execute? – ed22 Jul 26 '21 at 11:00
  • @ed22: Does this help? https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/async-return-types – BoltClock Jul 26 '21 at 13:07
  • @BoltClock, thanks but I still don't understand how async lambda parameter that is not awaited executes... – ed22 Jul 26 '21 at 14:37
  • @ed22: Async void methods are exclusively event handlers. Nothing is awaiting them, they just go off and do their own thing. – BoltClock Jul 26 '21 at 14:38
  • @ed22 An API is asking you to give it a parameter of type: method which returns a `Task`. Async lambda, like an async method, is a way for you to write such methods. If someone calls your async method or lambda, it will execute the code you wrote and the `Task` it returns will be set completed when the code is finished. Presumably, if someone asks you for such a method, they intend to call it and await. – relatively_random Feb 07 '22 at 16:12
59

And for those of you using an anonymous expression:

await Task.Run(async () =>
{
   SQLLiteUtils slu = new SQLiteUtils();
   await slu.DeleteGroupAsync(groupname);
});
Su Llewellyn
  • 2,660
  • 2
  • 19
  • 33
9

If you are inside a LINQ method syntax apply the async keyword right before the parameter:

 list.Select(async x =>
            {
                await SomeMethod(x);
                return true;
            });
Drilon Ahmetaj
  • 525
  • 5
  • 7
  • What does the `return true;` represents? – Theodor Zoulias Nov 15 '21 at 16:08
  • @TheodorZoulias sorry for the poor explanation. The return true; represents what each value of the list should return, in my case the list was List, so from one list you are creating another list with Select() method. For the sake of simplicity I removed my logic. The important part here is that I needed to call an awaitable method inside a lambda expression and that is done by putting the async keyword. – Drilon Ahmetaj Nov 17 '21 at 13:17
  • Drilon if the `list` is a `List`, then the `x` is a `bool`. This is clear. The `return true;` is not clear. Why would you return a constant value instead of the result of the `await SomeMethod(x)`, or at least the `x` itself? And where is this return value used? Your example does not assign the result of the `list.Select` to anything. Sorry, but for the time being I have to downvote the answer. You could try to improve it by editing it if you want. – Theodor Zoulias Nov 17 '21 at 13:35
  • You don't have to be sorry for what you are... The return depends on the awaitable method. Example. if SomeMethod returns not null , return true, else return false, and that will do a mapping of each vaule. But I did not want to provide all the code since it is irrelevant for the async keyword problem. – Drilon Ahmetaj Nov 18 '21 at 11:01