问题描述
我有一个问题,我还没有找到任何 answear.这是我使用线程和任务的第一个项目.当我的任务被取消时,它一直在执行耗时的方法.
I have a problem, that I could not find any answear yet. And this is my first project with use of threading and Tasks. When my task is cancelled, it keeps executing time consuming method.
现在我不知道如何与任务一起停止方法的执行.
Right now I have not idea how to stop execution of the method together with the task.
下面是一个循环,它运行任务.每个任务都运行一个 ParseHorseData
方法,该方法还运行其他几个方法.执行它们有时需要很多时间.
Below is a loop, that runs tasks. Every single task is running a ParseHorseData
method, that runs also several other methods. Execution of them takes sometimes a lot of time.
任务取消后,在await Task.WhenAll(tasks);
之前,需要很多时间.
After the task is cancelled, before await Task.WhenAll(tasks);
is completed, it takes a lot of time.
那么,正如问题中所说,有没有办法取消已取消任务中方法的执行?
So, as in the question, is there a way to cancel execution of method in cancelled task?
List<Task> tasks = new List<Task>();
int loopCounter = 0;
int taskCounter = 0;
//for all races in the file
for (int i = 0; i < _allRaces.Count; i ++)
{
int j = i;
if (TaskCancellation == true)
{
break;
}
Task task = Task.Run(async () =>
{
while (!_cancellationToken.IsCancellationRequested)
{
loopCounter++;
ProgressBarTick("Requesting historic data", loopCounter, _allRaces.Count, 0);
//if the race is from 2018
if (_allRaces[j].RaceDate.Year == 2018)
{
Category = _allRaces[j].RaceCategory;
Distance = _allRaces[j].RaceDistance.ToString();
//for all horses in the race
for (int h = 0; h < _allRaces[j].HorseList.Count; h++)
{
HorseDataWrapper horse = new HorseDataWrapper();
//TIME CONSUMING
horse = ParseHorseData(_allRaces[j].HorseList[h], _allRaces[j].RaceDate);
_allRaces[j].HorseList[h] = horse;
}
}
taskCounter++;
if (loopCounter >= _allRaces.Count)
{
ProgressBarTick("Testing on historic data", taskCounter, _allRaces.Count, 0);
}
}
}, _tokenSource.Token);
tasks.Add(task);
}
try
{
await Task.WhenAll(tasks);
}
catch (TaskCanceledException)
{
//
}
finally
{
_tokenSource.Dispose();
}
推荐答案
所有取消都是合作的.正在执行的方法必须将 CancellationToken
传递给它调用的方法,并且:
All cancellation is cooperative. The method being executed must pass the CancellationToken
into the methods that it calls, and either:
- 使用
ThrowIfCancellationRequested
定期轮询取消.这种方法更适合 CPU 密集型循环. - 使用
Register
取消操作.这种方法更适合与非基于CancellationToken
的取消系统交互.
- Periodically poll for cancellation using
ThrowIfCancellationRequested
. This approach is more appropriate for CPU-bound loops. - Take an action on cancellation using
Register
. This approach is more appropriate for interfacing with non-CancellationToken
-based cancellation systems.
在这种情况下,听起来轮询是合适的.我强烈建议通过 ThrowIfCancellationRequested
而不是 IsCancellationRequested
进行轮询,因为当一个任务被取消时,它应该在 await时抛出一个
OperationCanceledException
代码>编辑.这就是调用代码知道它已被取消的方式.
In this case, it sounds like polling is appropriate. I strongly recommend polling via ThrowIfCancellationRequested
and not IsCancellationRequested
, because when a task is canceled, it should throw an OperationCanceledException
when await
ed. This is how the calling code knows it has been canceled.
示例:
Task task = Task.Run(async () =>
{
while (true)
{
_cancellationToken.ThrowIfCancellationRequested();
...
//for all horses in the race
for (int h = 0; h < _allRaces[j].HorseList.Count; h++)
{
_cancellationToken.ThrowIfCancellationRequested();
HorseDataWrapper horse = new HorseDataWrapper();
horse = ParseHorseData(_allRaces[j].HorseList[h], _allRaces[j].RaceDate);
_allRaces[j].HorseList[h] = horse;
}
...
}
});
这篇关于有没有办法取消取消任务中方法的执行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!