如何将CancellationToken传递给WebApi操作?

3

我正在按照以下方式向WebApi发出请求:

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

我在控制器操作中使用HostingEnvironment,以便可以在后台线程中完成工作,并将IIS的取消令牌传递给我的服务方法,如下所示:

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

    return Ok();
}

现在我希望能够从客户端传递一个取消标记,以便用户可以取消请求,因此我创建了一个 CancellationTokenSource 并对客户端进行了以下更改:

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

并改变了行动:

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

    return Ok();
}

我的问题出现在这一行:

HostingEnvironment.QueueBackgroundWorkItem(async ct =>

如果我需要使用传递给操作的 ct,那么我该如何使用 IIS 需要传递给后台线程的 ct


不确定这是否有效。一旦令牌发送到服务器并且用户取消了它,那么服务器就不会收到通知了,对吗? - Peter Bons
1个回答

1
你需要做的是将你得到的两个取消标记(一个来自客户端,另一个来自HostingEnvironment)结合起来。你可以使用CancellationTokenSource.CreateLinkedTokenSource方法来完成这个任务。
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();
}

1
只是出于好奇,这是如何工作的?客户端发送请求,然后在客户端取消令牌(ct1),那么服务器是如何神奇地知道ct1已被取消的呢?在这种情况下,客户端是否还会发送另一个请求或者...? - Peter Bons
这也是我的假设。但为什么异步请求中会有CancellationToken呢? - Ivan-Mark Debono

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接