Очередь BankgroundJob с Hangfire в асинхронном действии в ASP.NET MVC заморозить приложение

У меня есть это действие на одном из моих контроллеров, которое вызывается другим методом, который также вызывается другим действием.

Все работает нормально, если я не пытаюсь поставить в очередь с Hangfire некоторые работы: _bankClient.FetchAndEnsureTransactionsAsync а также _bankClient.RefreshItemAsync, Это приводит к зависанию приложения (клиент, браузер останавливается, пока сервер еще работает). Я полагаю, это немного странно deadlockНо ничего из того, что я пробовал, похоже, не работает!

Кто-нибудь знает, как решить эту проблему?

я знаю Hangfire пока не поддерживает звонки async методы, поэтому у меня есть synchronous версия этого метода, который я в очереди.

НЕ рабочее действие

private async Task<ActionResult> ActionOnFinished(long itemId, ItemStatus status, Guid userId)
    {
        var seller = await _unitOfWork.CompanyRepository.GetCompanyByUserIdAsync(userId).ConfigureAwait(false);
        await _bankClient.CreateItemAndAccountsAsync(userId, seller.Id, itemId, seller.Name, seller.Siren.ToString()).ConfigureAwait(false);

        // TODO: use hangfire when available and fire this on BackgroundJob
        if (Properties.Settings.Default.EnableHangfire)
        {
            BackgroundJob.Schedule<IBankClientService>(bs => bs.FetchAndEnsureTransactions(userId), DateTimeOffset.Now.AddMinutes(1));
            BackgroundJob.Schedule<IBankClientService>(bs => bs.RefreshItem(userId), DateTimeOffset.Now.AddMinutes(1));
        }
        else
        {
            await _bankClient.FetchAndEnsureTransactionsAsync(userId).ConfigureAwait(false);
            await _bankClient.RefreshItemAsync(userId).ConfigureAwait(false);
        }

        return RedirectToAction(MVC.Dashboard.MyProfile());
    }

Рабочее действие:

 private async Task<ActionResult> ActionOnFinished(long itemId, ItemStatus status, Guid userId)
    {
        var seller = await _unitOfWork.CompanyRepository.GetCompanyByUserIdAsync(userId).ConfigureAwait(false);
        await _bankClient.CreateItemAndAccountsAsync(userId, seller.Id, itemId, seller.Name, seller.Siren.ToString()).ConfigureAwait(false);

        // TODO: use hangfire when available and fire this on BackgroundJob
        await _bankClient.FetchAndEnsureTransactionsAsync(userId).ConfigureAwait(false);
        await _bankClient.RefreshItemAsync(userId).ConfigureAwait(false);

        return RedirectToAction(MVC.Dashboard.MyProfile());
    }

Прецедентное действие вызывается закрытым методом:

private async Task<ActionResult> SelectActionByStatus(long itemId, ItemStatus status, Guid userId)
    {
        try
        {                
            if (status.Status == RefreshStatusValues.Finished)
            {
                return await ActionOnFinished(itemId, status, userId).ConfigureAwait(false);
            }

            return ActionOnError();
        }
        catch (Exception ex)
        {
            _logger.Error(ex, nameof(SelectBank));
            throw new ValidationFailureException(nameof(GetAccounts), ex.Message);
        }
    }

Это действие было вызвано другим действием:

public async virtual Task<ActionResult> CallBack(string item_id)
    {
        try
        {
            var itemId = long.Parse(item_id);

            var userId = CurrentUserId.Value;
            // as this action is being called by a child window whom is being closed we need to configure the awaiter with ConfigureAwait(false)
            var status = await _bankClient.CheckItemStatusAsync(userId, itemId).ConfigureAwait(false);

            return await SelectActionByStatus(itemId, status, userId).ConfigureAwait(false);
        }
        catch (Exception ex)
        {
            _logger.Error(ex, nameof(CallBack));
            return RedirectToAction(MVC.Bank.BankError());
        }
    }

СИНХРОННАЯ ВЕРСИЯ

public IEnumerable<Transaction> FetchAndEnsureTransactions(Guid userId)
    {
        try
        {
            return FetchAndEnsureTransactionsAsync(userId).ConfigureAwait(false).GetAwaiter().GetResult();
        }
        catch (Exception ex)
        {
            _logger.Error(ex, $"{nameof(FetchAndEnsureTransactions)}");
            throw;
        }
    }

public void RefreshItem(Guid userId)
    {
        try
        {
            RefreshItemAsync(userId).ConfigureAwait(false).GetAwaiter().GetResult();
        }
        catch (Exception ex)
        {
            _logger.Error(ex, $"{nameof(RefreshItem)}");
            throw;
        }
    }

0 ответов

Другие вопросы по тегам