I created a background service to process items in a queue as demonstrated here:
Unlike the example, items are added to the queue via a Web API method that looks something like this:
[HttpPut("queueworkitem")]
public async Task<ActionResult> QueueWorkItem() {
var collection = GetALargeCollection();
await _taskQueue.QueueBackgroundWorkItemAsync(async token => {
foreach (var item in collection) {
//do work here
}
});
return Ok();
}
I would like to provide a way for a caller to cancel a queued task in a subsequent request using a reference returned by QueueWorkItem. I tried the following, but CancellationTokenSource is not serializable. Is there some way to accomplish this?
[HttpPut("queueworkitem")]
public async Task<ActionResult> QueueWorkItem() {
var collection = GetALargeCollection();
var source = new CancellationTokenSource();
var cancellationToken = source.Token;
await _taskQueue.QueueBackgroundWorkItemAsync(async token => {
foreach (var item in collection) {
cancellationToken.ThrowIfCancellationRequested();
//do work here
}
});
return Ok(source);
}
[HttpPut("cancelworkitem")]
public Task<ActionResult> CancelWorkItem(CancellationTokenSource source) {
source.Cancel();
return Ok();
}
You can keep your cancellation token inside your task queue and use a unique key to find it later, for example:
create a
WorkItemclass/record to keep everything in one place:then you can store this key/token inside a dictionary: for example:
At the end, you can use it this way in your API:
This will work fine if you have only 1 server and you don't want to serialize and save your tasks in some storage. but if you need to run the tasks later, I would suggest checking out the Hangfire library which gives you exactly the same functionalities.