5

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() 
{
    // ?????
}
ca9163d9
  • 27,283
  • 64
  • 210
  • 413
  • assuming yout UI part is using MVC, here is a good blog post about binding cancellation token to HttpRequest in net core mvc https://andrewlock.net/using-cancellationtokens-in-asp-net-core-mvc-controllers/ you can abort your request if it is taking long time. Frontend might be using some ajax request that might have a button for calling `XMLHttpRequest.abort()` method. – Sharif Jan 09 '20 at 22:34
  • In my Blazor application, I will have a Cancel button to cancel the request. – ca9163d9 Jan 10 '20 at 05:31

1 Answers1

12

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.

Aage
  • 5,932
  • 2
  • 32
  • 57
Mark Davies
  • 1,447
  • 1
  • 15
  • 30