0

I have one AsyncPeriodicBackgroundWorkerBase base class(DataValidateWorker) which runs 1 minute interval.

I need to send the data I get from the DB to a third party web service and update the results in the db. A Web service response arrives in about 30-40 seconds. For this reason, I need to send Web service queries simultaneously, not sequentially.

For this reason, I wrote code in accordance with parallel programming as seen below. I cannot pull the database connection for the Task I wrote. DB connection closed, I got many errors like Executing. How can I create the db connection for my Task?

Would it be better to write this job in an external application (exe or service) instead of ABP?

public class DataValidateWorker : AsyncPeriodicBackgroundWorkerBase
{
private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly IDataFilter _dataFilter;

public DataValidateWorker(AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory, IDataFilter dataFilter, IUnitOfWorkManager unitOfWorkManager) : base(timer, serviceScopeFactory)
{
    _dataFilter = dataFilter;
    _unitOfWorkManager = unitOfWorkManager;
    Timer.Period = 60 * 1000; // 60 seconds
}

[UnitOfWork]
protected async override Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
{
    try
    {
        var notificationValidationRepository = workerContext.ServiceProvider.GetRequiredService<IRepository<NotificationValidation, int>>();
        var notificationValidationItems = await notificationValidationRepository.GetQueryableAsync();
        List<NotificationValidation> list = new List<NotificationValidation>();
        using (var uow = _unitOfWorkManager.Begin())
        {
            using (_dataFilter.Disable<IMultiTenant>())
            {
                list = notificationValidationItems.Where(x => x.RecordDateTime <= DateTime.Now && x.ValidationResult == (int)ValidationResult.NotStarted).ToList();
            }
        }
        NotificationValidationArgs jobArgs = new NotificationValidationArgs();
        foreach (var item in list)
        {
            jobArgs.notificationValidationId = item.Id;
            Task taskA = Task.Factory.StartNew(async (Object obj) =>
            {
                // doing some third party web service operations and db operations
            }, jobArgs);
        }
    }
    catch (Exception ex)
    {
        Logger.LogCritical(2001, ex, DateTime.Now.ToString() + " -> DataValidateWorker -> try 1 -> RDMS uow");
    }
}
}

1 Answers1

0

You don't await any of tasks, so lifetime of object ends while your task is still running.

Try to store all of the tasks in a collection and await them before method execution finishes.

Something like below:

public class DataValidateWorker : AsyncPeriodicBackgroundWorkerBase
{
    public DataValidateWorker(AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory) : base(timer, serviceScopeFactory)
    {
    }

    protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
    {
        var tasks = new List<Task>();
        foreach (var item in list)
        {
            tasks.Add(YourLongJob(arg)); // don't await here. collect in a collection
        }

        await Task.WhenAll(tasks); // wait until all of them is completed.
    }

    private async Task YourLongJob(object arg)
    {
        await Task.Delay(30 * 1000); // a long job
    }
}
enisn
  • 625
  • 7
  • 14