Ivan-Mark Debono
Ivan-Mark Debono

Reputation: 16330

How to pass CancellationToken to WebApi action?

I'm making a request to a WebApi as follows:

var response = client.PostAsJsonAsync(url, dto).Result;

I'm using HostingEnvironment in the controller action so I can do the work in a background thread, and pass IIS's cancellation token to my service method, as follows:

public IHttpActionResult MyAction(SearchDto dto)
{
    HostingEnvironment.QueueBackgroundWorkItem(async ct =>
    {
        //Do background work
        var result = await myService.DoWorkAsync(dto, ct);
    });

    return Ok();
}

Now I want to pass a cancellation token from the client, so that the user can cancel the request, so I created a CancellationTokenSource and did the following change on the client:

var response = client.PostAsJsonAsync(url, dto, cts.Token).Result;

And the change to the action:

public IHttpActionResult MyAction(SearchDto dto, CancellationToken ct)
{
    HostingEnvironment.QueueBackgroundWorkItem(async ct =>
    {
        //Do background work
        var result = await myService.DoWorkAsync(dto, ct);
    });

    return Ok();
}

My problem is the line:

HostingEnvironment.QueueBackgroundWorkItem(async ct =>

If I need to the use the ct I pass to the action, how am I going to use the ct that IIS needs to pass to the background thread?

Upvotes: 4

Views: 2383

Answers (1)

Sean
Sean

Reputation: 62532

What you need to do is combine the two cancellation tokens you've got, the first from the client and the second from the HostingEnvironment. You can do this with this CancellationTokenSource.CreateLinkedTokenSource method

public IHttpActionResult MyAction(SearchDto dto, CancellationToken ct1)
{
    HostingEnvironment.QueueBackgroundWorkItem(async ct2 =>
    {
        using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(ct1, ct2))
        {
            var result = await myService.DoWorkAsync(dto, linkedCts.Token);
        }
    });

    return Ok();
}

Upvotes: 1

Related Questions