• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
netcore_vue
博客园    首页    新随笔    联系   管理    订阅  订阅

ABP中使用HangFire和 Magicodes.IE(文件导出)中遇到的生命周期失效的解决

实现功能:

1,通过Magicodes.IE(不错的文件导入及导出组件,使用近5年了),导出10W+的数据;

2,前端VUE调用导出大数据接口,报Http499超时,考虑后端用HangFire后台作业来执行具体任务,执行完成,把执行的结果返回给前端;

实现动态导出功能的服务代码如下:

 public class OutputService : ITransientDependency
 {
     private readonly IUnitOfWorkManager _unitOfWorkManager;
     private readonly IBlobContainer<BlobCommonFileContainer> _fileContainer;
     public OutputService(
         IUnitOfWorkManager unitOfWorkManager,
         IBlobContainer<BlobCommonFileContainer> fileContainer)
     {
         _fileContainer = fileContainer;
         _unitOfWorkManager = unitOfWorkManager;
     }

     public async Task Export<T>(Guid Id, string fileName, List<T> list) where T : class, new()
     {
         using (var uow = _unitOfWorkManager.Begin(requiresNew: true, isTransactional: true))
         {
             IExporter _exporter = new ExcelExporter();//导出Excel
             var result = await _exporter.ExportAsByteArray<T>(list);
             result.ShouldNotBeNull();
             await _fileContainer.SaveAsync(fileName, result).ConfigureAwait(false);
             await uow.CompleteAsync();
         }
     }
 }

调用方式一:

 此处的坑:

1,异常吞没:如果 SaveAsync 方法内部有异常处理(例如 try-catch 块),并且异常被吞没(没有被记录或重新抛出),这可能导致方法在没有明显错误的情况下失败

2,后显示加上try-catch 块,报出了异常:

System.ObjectDisposedException
  HResult=0x80131622
  Message=Instances cannot be resolved and nested lifetimes cannot be created from this LifetimeScope as it (or one of its parent scopes) has already been disposed.
  Source=Autofac
  StackTrace:
   在 Autofac.Core.Lifetime.LifetimeScope.ThrowDisposedException() 在 Autofac.Core.Lifetime\LifetimeScope.cs 中: 第 314 行
   在 Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(ResolveRequest request) 在 Autofac.Core.Lifetime\LifetimeScope.cs 中: 第 177 行
   在 Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance) 在 Autofac\ResolutionExtensions.cs 中: 第 414 行
   在 Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable`1 parameters) 在 Autofac\ResolutionExtensions.cs 中: 第 306 行
   在 Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   在 Volo.Abp.BlobStoring.BlobNormalizeNamingService.NormalizeNaming(BlobContainerConfiguration configuration, String containerName, String blobName)
   在 Volo.Abp.BlobStoring.BlobContainer.<SaveAsync>d__22.MoveNext()
   在 Volo.Abp.BlobStoring.BlobContainerExtensions.<SaveAsync>d__0.MoveNext()

大体意思:

System.ObjectDisposedException 错误表明尝试从已经被释放(disposed)的 LifetimeScope 解析服务时出现了问题。在这种情况下,错误消息指出 Autofac 容器的一个作用域(或其父作用域)已经被释放,因此无法从中解析服务或创建嵌套的作用域。

以下是可能导致此异常的原因和解决方法:

  1. 作用域释放:

    • 确保你没有在完成请求处理之前释放了 Autofac 的作用域。在 ASP.NET Core 中,作用域通常与 HTTP 请求生命周期相关联。
  2. 依赖项注入问题:

    • 如果在 BlobContainer 或相关服务中使用了依赖注入,确保这些服务在作用域释放之前被正确解析。
  3. 异步方法和作用域:

    • 如果 SaveAsync 或其他异步方法在作用域被释放后仍在执行,它们可能会尝试解析服务,从而导致此异常。
  4. 使用 IAsyncLifetime 或 IDisposable:

    • 如果你的服务实现了 IAsyncLifetime 接口,确保在 DisposeAsync 方法中正确处理了作用域。如果实现了 IDisposable,确保在对象被释放前正确处理资源。
  5. 检查 BlobNormalizeNamingService 和 BlobContainer:

    • 检查 BlobNormalizeNamingService.NormalizeNaming 和 BlobContainer.SaveAsync 方法的实现,确保它们不会在作用域释放后执行。

解决问题,重新加上生命周期作用域,代码如下:

 public async Task<string> ExportFile(Guid id, List<string> exportName, List<CustomCondition> p_list)
 {
     id = Guid.NewGuid();
     using (var scope = _serviceProvider.CreateScope())
     {
         var service = scope.ServiceProvider.GetRequiredService<OutputService>();
         var _first = exportName.FirstOrDefault();
         string sql = "SELECT id,ParentItemCode,ParentItemDesc,ChildItemCode,ChildItemDesc,Qty,ChildItemUom FROM [dbo].[hx_bom]";
         var _list = await _dbDapperContext.QueryAsync<BomExportDto>(sql, null, databaseType: DatabaseType.Secondary);
         try
         {
             // 使用 service 执行工作
             await service.Export<BomExportDto>(id, _first, _list.ToList()).ConfigureAwait(false);
         }
         catch (Exception ex)
         {
             Console.WriteLine(ex.Message.ToString());
         }
         return id.ToString();
     }
 }

测试:

执行hangfire任务

 

 成功通过后台作业生成文件‘

 

posted @ 2024-06-13 22:09  梦想代码-0431  阅读(106)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3