I am calling same function in parallel using Task.Whenall().I And am trying to add functionality to stop execution using CancellationTokenSource .
CancellationTokenSource return true when I call Token.Cancel() but afterwards it changes to false and therefore token.IsCancellationRequested is always false.
CancellationTokenSource _tokenSource = new CancellationTokenSource();
[HttpPost]
public async Task<IActionResult> Runcase(List<string> products,string runnumber,string button)
{
var token = _tokenSource.Token;
try
{
if (ModelState.IsValid)
{
var productinfo = products;
List<string> productids = new List<string>(productinfo);
var runnum = runnumber;
string runid = "";
int count = productids.Count();
List<Task> tasks = new List<Task>();
int rawid = 0;
for (int i = 0; i < count; i++)
{
tasks.Add(RunServiceAsync(productids[i], runnum,rawid,token));
}
await Task.WhenAll(tasks);
ViewBag.completed = "Success";
return View();
}
else
{
ViewBag.productinfo = new MultiSelectList(_context.inputValuesConfigurations, "ProductID", "ProductName");
ModelState.AddModelError(string.Empty, "Please enter a valid data...");
return View();
}
}
catch(Exception ex)
{
return View();
}
}
When I call this function ,token return true
public void Stopexecution()
{
_tokenSource.Cancel();
}
But in below code it is always false
public async Task RunServiceAsync(string productids,string runnumber,int rawid,CancellationToken token)
{
using(var dbscope = _service.CreateScope())
{
var dbcontext = dbscope.ServiceProvider.GetRequiredService<AppDbContext>();
var productid = Convert.ToInt32(productids);
var inputvals = dbcontext.inputValuesConfigurations.FirstOrDefault(m => m.ProductID == productid);
var run = runnumber + '_' + inputvals.ProductID;
int count = 0;
bool completion1 = false; // for j
int totalCount = CountProductvalues(inputvals);
while (!completion1) //
{
var errorrun = dbcontext.errorlogs.Select(m => m.ProductID == productid).ToList().Count();
totalCount = completion == true ? errorrun : totalCount;
for (int j = rawid; j < totalCount; j++)
{
if(token.IsCancellationRequested)
{
token.ThrowIfCancellationRequested();
}
if(!completion) // Stop if First run complete
{
Inputvalues c1 = new Inputvalues(j, inputvals);
InputValuesViewmodel inputValues = new InputValuesViewmodel()
{
ProductID = productid,
STATE = c1.State,
AGE1 = c1.AGE1,
SEX1 = c1.SEX1,
UND_CLASS1 = c1.UND_CLASS1,
FACE_OPTIONS = 1,
FACE_SCHEDULE = "1ü" + c1.SOLVE_TARGET_YEAR + "0ü" + c1.FACE_SCHEDULE,
PREM_OPTIONS = premoption,
PAY_PREM_TARGET_ID = c1.PAY_PREM_TARGET_ID,
PAY_PREM_TARGET_YEAR = c1.PAY_PREM_TARGET_YEAR,
SOLVE_TARGET_ID = 1,
SOLVE_TARGET_YEAR = c1.SOLVE_TARGET_YEAR
};
await RecieveResponseasync(inputValues, run, j,productid);
//completion = j == totalCount ? true : false;
}
}
};
}
}
Calling Stopexecution()
$("#btnstop").click(function (e) {
$("#btnstart span").text("Rerun");
let btnstartval = $("#btnstart").val('Rerun');
e.preventDefault();
$.ajax({
url: "@Url.Action("Stopexecution", "CallService")",
type: "POST",
dataType: "json",
});
});
});
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
So the first issue here is that you have a CancellationTokenSource as a member of a controller. Controllers are transient, meaning they are created every time a request is made to it. So, you are creating a new token source every time that controller is called.
To fix this, you could make this static:
static CancellationTokenSource _tokenSource = new CancellationTokenSource();
Remember to reset that source every time a request is made… because once it’s cancelled, it’s cancelled for good. Also, then what happens if this endpoint gets called two or more times at the same time. You will have a race condition.
Second issue is: this isn’t a very “Controller-like” pattern. You should re-think how you are generating data. If a call to an endpoint takes longer than 100 ms, then you are going to run in to thread/socket starvation issues if your service gets hot.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0