我该在哪里标记Lambda表达式为异步?

296

我有这段代码:

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));
}

Resharper的检查抱怨了这个问题,报错信息是:“由于此调用未被等待,当前方法的执行在完成调用之前继续。请考虑将'await'运算符应用于调用结果”(在带有注释的行上)。

因此,我在它前面添加了“await”,但是我当然还需要在某个地方添加“async”-但在哪里呢?


1
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions#async-lambdas - samus
1
@samsara:不错,我想知道他们最终何时在C#规范之外记录了这一点。如果我没记错的话,当时问这个问题时没有任何文档存在。 - BoltClock
3个回答

460

要将lambda表达式标记为异步函数,只需在其参数列表前加上async

// 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);
}));

2
我从Visual Studio收到错误提示,Async void方法不受支持。 - Kevin Burton
1
@Kevin Burton:是的,异步 void 通常只限于事件处理程序。您正在使用的 API 要么不是异步的,要么有一个期望异步任务 lambda 的异步版本。 - BoltClock
@ed22:这个有帮助吗?https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/async-return-types - BoltClock
@BoltClock,谢谢你,但我仍然不明白未等待的异步lambda参数是如何执行的... - ed22
@ed22 一个 API 要求你提供一个返回 Task 类型的方法参数。Async lambda 和 async 方法一样,是你编写此类方法的一种方式。如果某人调用了你的 async 方法或 lambda,它将执行你编写的代码,并在代码完成时设置返回的 Task 已完成。假定如果有人向你请求这样的方法,他们意图调用它并等待。 - relatively_random
显示剩余2条评论

61

对于那些使用匿名表达方式的人:

await Task.Run(async () =>
{
   SQLLiteUtils slu = new SQLiteUtils();
   await slu.DeleteGroupAsync(groupname);
});

10

如果您在LINQ方法语法中,请在参数右侧添加async关键字:

 list.Select(async x =>
            {
                await SomeMethod(x);
                return true;
            });

return true; 代表什么? - Theodor Zoulias
@TheodorZoulias 对于我糟糕的解释感到抱歉。return true; 表示列表中每个值应该返回什么,在我的情况下,列表是List<bool>,因此从一个列表创建另一个列表使用Select()方法。为了简单起见,我删除了我的逻辑。这里重要的部分是我需要在lambda表达式中调用可等待方法,这可以通过添加async关键字来完成。 - Drilon Ahmetaj
如果listList<bool>,那么x就是一个bool。这很清楚。但是return true;不清楚。为什么要返回一个常量值而不是await SomeMethod(x)的结果,或者至少是x本身的结果呢?这个返回值在哪里使用?你的例子没有将list.Select的结果分配给任何东西。抱歉,但目前我必须对这个答案投反对票。如果您愿意,可以通过编辑来改进它。 - Theodor Zoulias
你不必为自己的所作所为感到抱歉...返回值取决于可等待方法。例如,如果SomeMethod返回非空值,则返回true,否则返回false,并将每个值进行映射。但是,由于异步关键字问题与此无关,因此我不想提供所有代码。 - Drilon Ahmetaj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接