ASP.NET MVC и библиотека MediatR, странное поведение

328
14 февраля 2017, 17:16

В одном из проектов подключена библиотека MediatR.

Используя абстракции из данной библиотеки определил команду:

public class TestCommand: IRequest
{ }

и обработчик данной команды:

public class TestHandler : IAsyncRequestHandler<TestCommand>
{
    public Task Handle(TestCommand command)
    {
        return Task.Factory.StartNew(() =>
        {
            // Здесь намеренно бросается исключение.
            throw new ApplicationException();
        });
    }
}

Далее в контроллер инжектится сам IMediator, через который мы можем вызвать нужный обработчик для конкретной команды.

Контроллер:

public class HomeController : Controller
{
    private readonly IMediator _mediator;
    public HomeController(IMediator mediator)
    {
        _mediator = mediator;
    }
    public  ActionResult Index()
    {
        try
        {
            // Передаем команду, тем самым вызываем обработчик данной команды - TestHandler.
            _mediator.Send(new TestCommand()).Wait();
        }
        catch (Exception e)
        {
            // Сюда никогда не попадаем 
        }
        return View();
    }
}

Суть проблемы:

Как можно заметить, в методе Handle класса TestHandler, который обрабатывает команду TestCommand создается и возвращается новая задача, в которой просто бросается исключение ApplicationException.

Далее в экшене Index контроллера Home, к возвращаемой из TestHandler.Handle задаче применен метод Wait(), который должен дождаться ее выполнения. Так как в возвращенной задаче бросается исключение ApplicationException мы по идее должны попасть в блок catch, но этого не происходит, вместо этого, такое ощущение, что возникает какой-то deadlock.

Собственно вопрос, это баг в библиотеке или я что-то упустил и не заметил и данное поведение нормально?

P.S. Если заменить

 _mediator.Send(new TestCommand()).Wait();

на

await _mediator.Send(new TestCommand());

то поведение будет ожидаемым, т.е. мы попадем в блок catch. Но лично мне хотелось бы понять, почему код перестает работать если используется метод Wait()

Answer 1

Автор библиотеки не удосужился вызвать ConfigureAwait(false) (RequestHandler.cs), так что внутри библиотеки произошёл захват контекста, а вы вызовом Wait() заблокировали поток, в который должно вернуться управление, так что произошёл классический deadlock с async/await, можете почитать детальный разбор тут Еще один аргумент за ConfigureAwait(false) в библиотеках

READ ALSO
Удаление объекта с ListView через MenuFlyout

Удаление объекта с ListView через MenuFlyout

Привет всемРебят, помогите исправить глупейшую ошибку в логике:

321
Сокращённая запись if(class != null) class.method unity C#

Сокращённая запись if(class != null) class.method unity C#

как записать более кратко

327
OpenCvSharp сегментация методом водораздела

OpenCvSharp сегментация методом водораздела

Необходимо выполнить сегментацию водоразделом для дальнейшей работыНашла на openCv, но не до конца получается преобразовать в OpenCvSharp

438
Что такое Instance в C#?

Что такое Instance в C#?

Недавно начал баловаться с unity, стал смотреть примеры скриптов и наткнулся на такую конструкцию:

332