await 仅使用 lambda 表达式
await with lambda expressions only
我无法找到正确的语法来使用 await 和 lambda 表达式(匿名 lambda 方法)。所有示例似乎都使用了用 async 关键字声明的实际方法。让我描述一下我想要的:
...code in UI thread...
Customer cust = null;
using (DataContext context = new DataContext()) // I want to run this async
{
cust = context.Customers.Single(c => c.Id == 1);
}
...continue code in UI thread...
为了在数据库查询期间不阻塞UI线程,我会写:
...code in UI thread...
Customer cust = null;
Task.Run(() =>
{
using (DataContext context = new DataContext())
{
cust = context.Customers.Single(c => c.Id == 1);
}
});
...continue code in UI thread...
这当然行不通,因为 UI 线程会在任务启动后继续。我不能在 Task
上 Wait()
,因为那样会阻塞 UI 线程。简单地在 Task.Run()
前面添加 await
不会编译。我能想到的最好的事情是:
...code in UI thread...
Customer cust = null;
Parallel.Invoke(async () =>
{
await Task.Run(() =>
{
using (DataContext context = new DataContext())
{
cust = context.Customers.Single(c => c.Id == 1);
}
});
});
...continue code in UI thread...
现在我还没有对此进行测试,所以我不知道这是否真的有效或仍然阻塞 UI 线程。但无论如何我都不喜欢 Parallel.Invoke
调用,我确信有一种调用匿名方法的 cleaner/nicer 方式,但目前我想不出任何办法。我遇到的主要问题是,我的直觉告诉我,为了实现异步继续(调用数据库查询异步,在此期间不要阻塞 UI 线程,然后继续执行异步调用之后的任何代码UI 线程),第一行必须以 await ...
开头
例如:
...code in UI thread...
Customer cust = null;
await ...(whatever follows)
...continue code in UI thread...
或者甚至:
...code in UI thread...
Customer cust = await ...(some anonymous lambda method returning Customer)
...continue code in UI thread...
所以我的问题是。如何在不使用任何命名方法,只使用lambda表达式(匿名lambda方法)的情况下正确编写这段代码。
您可以使用 Task.Run
和 await
returned 任务。您只需要用 async
关键字标记此方法并将其设置为 return a Task
:
async Task FooAsync()
{
Customer cust = null;
await Task.Run(() =>
{
using (DataContext context = new DataContext())
{
cust = context.Customers.Single(c => c.Id == 1);
}
});
}
现在,如果这是顶级 UI 事件处理程序,它不能 return 和 Task
,您需要使用 async void
。这仅适用于 UI 事件处理程序。
如果你不能让你的方法 async
并且你仍然想保持操作异步你可以注册 UI 线程操作作为 ContinueWith
和 [= 的延续20=] 以确保继续在 UI 线程上运行:
void Foo()
{
Customer cust = null;
var task = Task.Run(() =>
{
using (DataContext context = new DataContext())
{
cust = context.Customers.Single(c => c.Id == 1);
}
});
task.ContinueWith(antecedent =>
{
// ...continue code in UI thread...
}, TaskScheduler.FromCurrentSynchronizationContext());
}
我无法找到正确的语法来使用 await 和 lambda 表达式(匿名 lambda 方法)。所有示例似乎都使用了用 async 关键字声明的实际方法。让我描述一下我想要的:
...code in UI thread...
Customer cust = null;
using (DataContext context = new DataContext()) // I want to run this async
{
cust = context.Customers.Single(c => c.Id == 1);
}
...continue code in UI thread...
为了在数据库查询期间不阻塞UI线程,我会写:
...code in UI thread...
Customer cust = null;
Task.Run(() =>
{
using (DataContext context = new DataContext())
{
cust = context.Customers.Single(c => c.Id == 1);
}
});
...continue code in UI thread...
这当然行不通,因为 UI 线程会在任务启动后继续。我不能在 Task
上 Wait()
,因为那样会阻塞 UI 线程。简单地在 Task.Run()
前面添加 await
不会编译。我能想到的最好的事情是:
...code in UI thread...
Customer cust = null;
Parallel.Invoke(async () =>
{
await Task.Run(() =>
{
using (DataContext context = new DataContext())
{
cust = context.Customers.Single(c => c.Id == 1);
}
});
});
...continue code in UI thread...
现在我还没有对此进行测试,所以我不知道这是否真的有效或仍然阻塞 UI 线程。但无论如何我都不喜欢 Parallel.Invoke
调用,我确信有一种调用匿名方法的 cleaner/nicer 方式,但目前我想不出任何办法。我遇到的主要问题是,我的直觉告诉我,为了实现异步继续(调用数据库查询异步,在此期间不要阻塞 UI 线程,然后继续执行异步调用之后的任何代码UI 线程),第一行必须以 await ...
开头
例如:
...code in UI thread...
Customer cust = null;
await ...(whatever follows)
...continue code in UI thread...
或者甚至:
...code in UI thread...
Customer cust = await ...(some anonymous lambda method returning Customer)
...continue code in UI thread...
所以我的问题是。如何在不使用任何命名方法,只使用lambda表达式(匿名lambda方法)的情况下正确编写这段代码。
您可以使用 Task.Run
和 await
returned 任务。您只需要用 async
关键字标记此方法并将其设置为 return a Task
:
async Task FooAsync()
{
Customer cust = null;
await Task.Run(() =>
{
using (DataContext context = new DataContext())
{
cust = context.Customers.Single(c => c.Id == 1);
}
});
}
现在,如果这是顶级 UI 事件处理程序,它不能 return 和 Task
,您需要使用 async void
。这仅适用于 UI 事件处理程序。
如果你不能让你的方法 async
并且你仍然想保持操作异步你可以注册 UI 线程操作作为 ContinueWith
和 [= 的延续20=] 以确保继续在 UI 线程上运行:
void Foo()
{
Customer cust = null;
var task = Task.Run(() =>
{
using (DataContext context = new DataContext())
{
cust = context.Customers.Single(c => c.Id == 1);
}
});
task.ContinueWith(antecedent =>
{
// ...continue code in UI thread...
}, TaskScheduler.FromCurrentSynchronizationContext());
}