Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 仅使用lambda表达式等待_C#_.net_Task Parallel Library_Async Await_C# 5.0 - Fatal编程技术网

C# 仅使用lambda表达式等待

C# 仅使用lambda表达式等待,c#,.net,task-parallel-library,async-await,c#-5.0,C#,.net,Task Parallel Library,Async Await,C# 5.0,我很难找到正确的语法,以便在lambda表达式(匿名lambda方法)中使用wait。所有示例似乎都使用使用async关键字声明的实际方法。让我描述一下我想要什么: ...code in UI thread... Customer cust = null; using (DataContext context = new DataContext()) // I want to run this async { cust = context.Customers.Single(c =>

我很难找到正确的语法,以便在lambda表达式(匿名lambda方法)中使用wait。所有示例似乎都使用使用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线程将在任务启动后继续。我无法对
任务
执行
等待()
,因为这会阻塞UI线程。只需在任务前面添加
wait
。Run()
不会编译。我能想到的最好的办法是:

...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线程。但是我不喜欢并行调用
。调用无论如何,我确信有一种更干净/更好的方法来调用匿名方法,但目前我想不出什么。我还有一个主要的问题,就是我的直觉告诉我,为了实现异步继续(调用数据库查询异步,在此期间不要阻塞UI线程,然后继续执行UI线程上异步调用之后的任何代码),第一行必须以wait…
例如:

甚至可能:

...code in UI thread...
Customer cust = await ...(some anonymous lambda method returning Customer)
...continue code in UI thread...

所以我的问题是。如何在不使用任何命名方法的情况下正确编写这段代码,只使用lambda表达式(匿名lambda方法)。

您可以使用
任务。运行
并等待返回的任务。您只需使用
async
关键字标记此方法,并使其返回
任务

async Task FooAsync()
{
    Customer cust = null;
    await Task.Run(() => 
    {
       using (DataContext context = new DataContext())
       {
          cust = context.Customers.Single(c => c.Id == 1);
       }
    });
}
现在,如果这是顶级UI事件处理程序,它不能返回
任务
,您需要使用
async void
。这仅适用于UI事件处理程序

如果无法使方法
异步
,并且仍然希望保持操作异步,则可以使用
ContinueWith
TaskScheduler将UI线程操作注册为一个延续。从CurrentSynchronizationContext
确保延续在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放在Task.Run之前应该不会有任何问题。@erikkallen-“await”运算符只能在异步方法中使用。考虑用“AsiNC”修饰符标记该方法,并将其返回类型改为“任务”。然后执行错误提示所示的信息。我特别想知道如何在不修改外部处理程序/方法的情况下实现“wait”(尽管我在帖子中没有提到这一点,因为我不知道这是唯一的方法)。有时您无法更改方法或处理程序,而我发现,多亏了i3arnon的讨论,在这些情况下,您根本无法使用“wait”。@Marko我认为您不太明白
wait
背后的意思。如果你这样做了,约束将非常明显。没有什么能阻止您编写一个从任何地方调用的
async void
(甚至
async Task
)方法,
async
方法的调用方不一定是
async
本身。当然,这通常不是一个好主意,但是UI事件处理程序实际上是存在
异步void
方法的唯一原因
async
不是签名的一部分,它只是对编译器的一个提示-C#团队非常重视维护兼容性。假设我不能用async声明我的方法。我必须遵循void Foo(),但我仍然想在它里面等待,我该怎么做呢?是类似于我提出的Parallel.Invoke的方法,还是如何调用匿名的'async()=>{}方法?编辑:.Single()是不支持异步的简单LINQ2SQL。@Marko如果您的方法不能是
async
,则不能使用
wait
。您可以启动一个
async
操作,并使用
任务对其进行阻止。等待
,或者您可以启动它并继续操作,而不必等待它。您可以同步等待、异步等待或根本不等待,没有其他选择。@Marko如果该方法是第三方方法,那么您究竟是如何编写代码作为该方法的实现的?如果您正在为该方法编写代码,可以将其设置为
async
@Marko
async
关键字不是签名的一部分
async
可以应用于返回
任务
任务
无效
的任何方法。UI事件处理程序(以及大多数(如果不是所有的话)返回
void
,这就是
async void
的作用。@Marko如果您只是尝试添加它,您会发现它根本不是问题。
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());
}