Without MediatR - Async

Arialdo Martini — 29/08/2023 — C# MediatR

Async

With MediatR

Both send and publish are asynchronous from the IMediator side, with corresponding synchronous and asynchronous-based interfaces/base classes for requests/responses/notification handlers.

So a handler can be make async as follows:

public class PingHandler : IRequestHandler<Ping, Pong>
{
    public async Task<Pong> Handle(Ping request, CancellationToken cancellationToken)
    {
        await DoPong(); // Whatever DoPong does
    }
}

code

Without MediatR

The plain OOP approach relies on the native C# functionalities, so of course handler methods can be made async:


interface IPingHandler
{
    Task<Pong> Handle(Ping request);
}

class PingHandler : IPingHandler
{
    async Task<Pong> IPingHandler.Handle(Ping request)
    {
        // do work
        return await Task.FromResult(new Pong());
    }
}

code

FAQs

Which approach is preferrable?

Answer
With MediatR the IRequestHandler interface imposes returning a Task.
With OOP there are no constraints on the signature:

interface IPingHandler
{
    Pong Handle(Ping request);
}

class PingHandler : IPingHandler
{
    Pong IPingHandler.Handle(Ping request)
    {
        // do work
        return new Pong();
    }
}

Can IMediatR be synchronous?

Answer
No. From the IMediator side, the interface is async-only.

See the discussion on the Synchronous .Send() and Synchronous RequestHandlers and await on MediatR GitHub Issues.

Is it possible to have two handlers for the same class, one synchronous and the other asynchronous?

Answer
With MediatR no, it is not. A single handler handling multiple requests requires defining 2 separate Request classes.

With plain OOP, it is a matter of defining an overload or a separate handler method:

interface IPingHandler
{
    Task<Pong> HandleAsync(Ping request);
    Pong Handle(Ping request);
}

code

See a discussion on StackOverflow.

References

Comments

GitHub Discussions