Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cancel the query sent by MediatR?

Tags:

c#

blazor

mediatr

I'm using MediatR in .Net core 3.1 Blazor application. The following are the query and its handler.

public class GetSaleQuery : IRequest<SaleVm>
{
    public GetSaleQuery(string id)
    {
        Id = id;
    }

    public string Id { get; }
}

public class GetSaleQueryHandler : IRequestHandler<GetaQuery, SaleVm>
{
    public async Task<SaleVm> Handle(GetSaleQuery request, CancellationToken cancellationToken)
    {
        var q = await _context.Table1
            .ToListAsync(cancellationToken).ConfigureAwait(false);
        return ...;
    }
}

And in the UI part, the following is used to send query request.

async Task SearchClicked() 
{
    sendResult = await mediator.Send(new GetSaleQuery{ Id = id });
    // page will use sendRest to display the result  .....
}

Now I need to add a Cancel button to let user to cancel the long running query. How to pass the cancellation token to the query handler GetSaleQueryHandler.Handle()?

async Task CancelButtonClicked() 
{
    // ?????
}
like image 516
ca9163d9 Avatar asked Jan 25 '23 10:01

ca9163d9


1 Answers

This is essentially what the cancellation token is there for, if you look at the mediatr Send method you'll see tha it has a cancellation token as an optional parameter:

Task<object> Send(object request, CancellationToken cancellationToken = default (CancellationToken));

You can read more about them here: https://learn.microsoft.com/en-us/dotnet/api/system.threading.cancellationtoken?view=netframework-4.8

A CancellationToken enables cooperative cancellation between threads, thread pool work items, or Task objects. You create a cancellation token by instantiating a CancellationTokenSource object, which manages cancellation tokens retrieved from its CancellationTokenSource.Token property. You then pass the cancellation token to any number of threads, tasks, or operations that should receive notice of cancellation. The token cannot be used to initiate cancellation. When the owning object calls CancellationTokenSource.Cancel, the IsCancellationRequested property on every copy of the cancellation token is set to true. The objects that receive the notification can respond in whatever manner is appropriate.

So to do what you are asking to do when you run your query you want to return a cancelation token:

CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;

var result = await _mediator.Send(new Operation(), token);
return source ;

Then when you Cancel you would need to use that cancellation token to, well cancel the operation:

void Cancel(CancellationTokenSource token)
{
  token.Cancel();
}

Hope this helps.

like image 128
Mark Davies Avatar answered Jan 28 '23 15:01

Mark Davies