Autofac拦截异步执行顺序

时间:2015-10-07 13:59:44

标签: c# async-await autofac interception

所以我有这个课程:

public class MappingBootstrap : IMappingBootstrap
{
    public virtual async Task Map()
    {
        // Order is very important

        await this.mapper1.Map();

        await this.mapper2.Map();

        await this.mapper3.Map();

        await this.mapper4.Map();
    }
}

我有Autofac Interceptor:

public class LoggingInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        var methodReference = Guid.NewGuid();
        Console.WriteLine($"Calling {invocation?.Method?.DeclaringType?.Name}.{invocation?.Method?.Name} : {methodReference}");

        var startNew = Stopwatch.StartNew();

        invocation?.Proceed();

        startNew.Stop();

        Console.WriteLine($"{methodReference} : Done, time taken: {startNew.ElapsedMilliseconds}ms");
    }
}

这会产生输出:

  

调用IMapperBootstrap.Map:54425559-71fe-4f23-ab47-d0f3371ec819
   调用IMapper1.Map:51babb34-fa83-42ed-84e7-a1e979528116
   51babb34-fa83-42ed-84e7-a1e979528116:完成,所用时间:219毫秒
   54425559-71fe-4f23-ab47-d0f3371ec819:完成,所用时间:221毫秒
   调用IMapper2.Map:41c812a2-d82d-48f6-9b8d-139b52eb28e3
   41c812a2-d82d-48f6-9b8d-139b52eb28e3:完成,所用时间:9ms
   调用IMapper3.Map:c91bed04-8f86-47d3-a35a-417e354c2c5f
   c91bed04-8f86-47d3-a35a-417e354c2c5f:完成,所用时间:994ms
   调用IMapper4.Map:035cad27-1ba8-4bd1-b85f-396f64998d97
   035cad27-1ba8-4bd1-b85f-396f64998d97:完成,所用时间:18ms

正如您所看到的,MappingBoostrap.Map在第一个Mapper1.Map之后完成,而不是在我完成所有功能之后的预期。的为什么吗

Autofac配置:

builder.Register(context => new LoggingInterceptor());

builder
    .RegisterAssemblyTypes(typeof(Bootstrapper).Assembly)
    .Where(x => x.Namespace.Contains("Mapping"))
    .AsImplementedInterfaces()
    .EnableInterfaceInterceptors()
    .InterceptedBy(typeof(LoggingInterceptor));

1 个答案:

答案 0 :(得分:5)

  

为什么?

当您调用这样的异步方法时:

mapping.Map();

只有启动方法。这是how asynchronous methods work(我在博客上解释)。如果您await异步方法返回的任务,那么当前方法将暂停,直到异步方法完成:

await mapping.Map();

对于拦截理想解决方案是使ProceedIntercept方法异步:

public async Task InterceptAsync(IInvocation invocation)
{
  ...
  await invocation?.ProceedAsync();
  ...
}

不幸的是,Autofac没有内置的异步方法理解,所以这是不可能的。相反,您必须调用Proceed,只需启动异步方法。异步方法返回Task,表示该方法的执行。要挂钩方法的完成,您应该用您自己的{em>替换 {/ 1}}。

对于普通的Task - 返回方法,您可以使用以下内容:

Task