如何以明显的方式证明不同的执行顺序

Kon*_*ten 0 c# async-await .net-core

我想以一种直白的方式演示这个异步示例:

Thing[] stuff = await Context.Things
    .Where(a => true)
    .ToArrayAsync();

Console.WriteLine("Beep");
Run Code Online (Sandbox Code Playgroud)

将以与同步版本不同的顺序执行:

Thing[] stuff = Context.Things
    .Where(a => true)
    .ToArray();

Console.WriteLine("Boop");
Run Code Online (Sandbox Code Playgroud)

我想表明第二个版本始终在打印输出之前创建数组,而第一个版本的执行情况可能有所不同。

不知道该怎么做,显然很清楚。

Gur*_*ron 6

我想以一种直白的方式演示这个异步示例:
将如何以与同步版本不同的顺序执行

但你不能,因为两个版本都会在Console.WriteLine("Boop");. 在第一个示例中await,将停止方法执行,直到异步操作完成。

对于数据库上下文来说,此类实验并不那么容易,因为您将需要一些副作用。使用起来更方便Task.Delay异步模拟;

您的第一个片段可以更改为:

var array = await Task.Run(async () =>
{
    await Task.Delay(500); // simulate db call
    Console.WriteLine("Array created");
    return new int[]{};
});

Console.WriteLine("Beep"); 
Run Code Online (Sandbox Code Playgroud)

然后您可以将其与以下内容进行比较:

var task = Task.Run(async () =>
{
    await Task.Delay(500); // simulate db call
    Console.WriteLine("Array created");
    return new int[]{};
});

Console.WriteLine("Beep"); 

var array = await task;
Run Code Online (Sandbox Code Playgroud)

至于试图证明 EF Core 调用的异步性质(1. 假设您正在使用此 ORM 2. 假设您没有查询 Oracle 数据库,据我所知,该数据库仍然不提供真正的异步客户端),您将需要找到一种方法来注入您的副作用。对于相对简单的方法来执行此操作,您可以查看EF Core 拦截器或事件,例如ChangeTracker.Tracked或仅启用日志记录和/或使用诊断侦听器

例如(应该在 EF7 中工作):

class ObjectCreatedLoggerInterceptor : IMaterializationInterceptor
{
    public object CreatedInstance(MaterializationInterceptionData materializationData, object entity)
    {
        Console.WriteLine("Array element created");
        return entity;
    }
}

public class SomeContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.AddInterceptors(new ObjectCreatedLoggerInterceptor());
        base.OnConfiguring(optionsBuilder);
    }
}
Run Code Online (Sandbox Code Playgroud)

"Array element created"每次 EF 创建对象时都会写入(查询应至少返回一条记录)。