Очередь 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;
}
}