IsCancellationRequested is always false



我正在使用Task并行调用相同的函数。Whenall((。我正在尝试使用CancellationTokenSource添加停止执行的功能。CancellationTokenSource在调用Token时返回true。Cancel((,但之后它变为false,因此变为token。IsCancellationRequested始终为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();
}
}

当我调用此函数时,token返回true

public void Stopexecution()
{
_tokenSource.Cancel();
}

但在下面的代码中,它总是错误的

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;
}
}
};
}
}

调用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",
});
});
});

所以这里的第一个问题是您有一个CancellationTokenSource作为控制器的成员。控制器是瞬态的,这意味着每次向其发出请求时都会创建它们。因此,每次调用该控制器时,都会创建一个新的令牌源。

要解决此问题,您可以将其设置为静态:

static CancellationTokenSource _tokenSource = new CancellationTokenSource();

请记住,每次发出请求时都要重置该源。。。因为一旦取消,它就会永远取消。此外,如果这个端点同时被调用两次或两次以上,会发生什么。你将有比赛条件。

第二个问题是:这不是一个非常";控制器类";图案您应该重新思考如何生成数据。如果对端点的调用花费的时间超过100毫秒,那么如果您的服务变热,您将遇到线程/套接字饥饿问题。

最新更新