如何在依赖注入中使用异步方法

时间:2019-11-07 12:10:04

标签: c# asp.net-core dependency-injection async-await

我正在使用 .net核心(2.2)Web应用程序,并且具有一个控制器,该控制器负责进行按需数据同步处理。同样,我保留了一个按钮,单击该按钮会触发对服务的异步方法的调用。

在内部,此服务调用在操作以下进行处理

  1. 从数据库中获取数据以进行数据同步
  2. 将数据拆分为批处理以进行数据同步处理
  3. 为相关批次数据准备数据模型
  4. 将准备好的数据批发送到目标消息队列

为了从服务内部与数据库进行交互,使用IOC /依赖注入(即通过构造函数)提供了 Db上下文对象。

为了确定问题原因,我使用多种方式进行服务方法调用:

  • 使用Task.Run()调用异步方法
  • 在没有Task.Run()的情况下调用异步方法
  • 使用Task.Run()调用同步方法
  • 使用ConfigWait(true)调用异步方法

在所有情况下,它都没有改变,仍然得到DbContext对象的 ObjectDisposedException

  

在更多地了解IOC的范围系统时,在我看来   一旦响应是作用域就被分配给db-context对象   提供给用户。

代码段,其中包含最少的行,如下所示:

AzureSearchIndexController.cs

public class AzureSearchIndexController : Controller
{
   [HttpGet]
   public IActionResult StartIndex()
   {
      _azureSearchDataSyncService.StartIndexingAsync(_siteId, _siteName);
   }
}

AzureSearchDataSyncService.cs

public class AzureSearchDataSyncService : IAzureSearchDataSyncService
{
   public AzureSearchDataSyncService(JobContext context,
            ICacheHandler<AzureSearchDataSyncModel> cacheHandler,
            AzureJobsTopicBus azureJobsTopicBus)
   {
      _context = context;
      _cacheHandler = cacheHandler;
      _azureJobsTopicBus = azureJobsTopicBus;
      azureSearchDataSyncModel = new AzureSearchDataSyncModel();
   }

   public async Task StartIndexingAsync(int siteId, string siteName)
   {
      try
      {
         int fetchedData = 0;
         int _batchSize = 10;
         List<AzureJobMessageModel> azureJobMessages = new List<AzureJobMessageModel>();

         var jobsToAdd_Update= GetData(siteId);
         while (dataSyncModel.SyncStatus && 
            fetchedData < jobsToAdd_Update.Count)
         {
            var batchData = jobsToAdd_Update.Skip(fetchedData)
                          .Take(_batchSize - azureJobMessages.Count)
                          .ToList();
            if (batchData.Count <= 0)
               continue;

            azureJobMessages.AddRange( 
               PrepareAzureJobMessageModel( 
                      PrepareAzureSearchIndexerModel(batchData), 
                  EntityActionEnum.updated)
            );

            fetchedData += batchData.Count();

            if (azureJobMessages.Count >= _batchSize)
            {
               //Method sending batch data
               await _azureJobsTopicBus.SendMessageAsync(azureJobMessages);
               dataSyncModel.ProcessedData += azureJobMessages.Count();
               dataSyncModel.ProcessedBatches += 1;
               azureJobMessages = new List<AzureJobMessageModel>();
            }
         }
      }
      catch(Exception ex)
      {
          throw ex;
      }
   }
}

所需结果:希望在单击按钮时采用异步模式的数据同步过程。

实际结果:

  

获取错误“ ObjectDisposedException-无法访问已处置的对象   (db-context)”

。有人对此有任何想法吗?

注意:-我不想使操作方法异步。我将在服务方法或包含CRUD操作逻辑的CRUD操作中使用此方法调用。我希望数据同步逻辑在后台运行,而不影响CRUD操作的响应时间。

1 个答案:

答案 0 :(得分:1)

由于未等待服务调用,因此响应在服务之前完成,这将处理上下文。服务尝试访问上下文时导致错误。

使操作异步,然后等待服务

public class AzureSearchIndexController : Controller {

    //...

   [HttpGet]
   public async Task<IActionResult> StartIndex() {

        //...

        await _azureSearchDataSyncService.StartIndexingAsync(_siteId, _siteName);

        //...
    }
}