只有在调用 ThrowIfCancellationRequested 时才会取消任务
Task is cancelled only when ThrowIfCancellationRequested is called
我有一个无限循环的任务。
我有一个 CancellationToken,我将其传递给关于实际 ExecutePoll 函数的 Task.Run 调用。
我等了几秒钟然后取消令牌。
取消任务时应该 运行 有一个继续。
如果我显式调用 cancellationToken.ThrowIfCancellationRequested();,那么这个延续只有 运行s。如果我只是跳出循环,任务总是处于状态:RanToCompletion
任何人都可以分享一些关于我在这里出错的信息吗?
代码:
using System.Threading;
using System.Threading.Tasks;
namespace TaskCancellationTest
{
class Program
{
private static CancellationTokenSource _pollProcessTokenSource;
static async Task Main(string[] args)
{
InitPollingProcess();
await Task.Delay(5000);
Console.WriteLine("Cancelling loop");
_pollProcessTokenSource.Cancel();
Console.WriteLine("Loop cancelled");
Console.ReadLine();
}
private static void InitPollingProcess()
{
try
{
_pollProcessTokenSource = new CancellationTokenSource();
Task pollForListenerConfigs = Task.Run(async () =>
{
await ExecutePoll(_pollProcessTokenSource.Token);
},
_pollProcessTokenSource.Token);
pollForListenerConfigs.ContinueWith(_ =>
{
Console.WriteLine("Poll process stopped!");
}, TaskContinuationOptions.OnlyOnCanceled);
pollForListenerConfigs.ContinueWith(t =>
{
Console.WriteLine($"Task status: {t.Status}");
});
}
catch (Exception ex)
{
Console.WriteLine($"Poll process failed with Exception:\n {ex.Message}");
}
}
private static async Task ExecutePoll(CancellationToken cancellationToken)
{
while (true)
{
if (cancellationToken.IsCancellationRequested)
{
Console.WriteLine("Exit from poll loop!");
//cancellationToken.ThrowIfCancellationRequested(); // UNCOMMENT TO MAKE CONTINUATION RUN
break;
}
Console.WriteLine("Looping...");
await Task.Delay(1000);
}
}
}
}
没有错,解释的很好here:
You can terminate the operation by using one of these options:
By simply returning from the delegate. In many scenarios this is sufficient; however, a task instance that is canceled in this way
transitions to the TaskStatus.RanToCompletion state, not to the
TaskStatus.Canceled state.
By throwing a OperationCanceledException and passing it the token on which cancellation was requested. The preferred way to do this is
to use the ThrowIfCancellationRequested method. A task that is
canceled in this way transitions to the Canceled state, which the
calling code can use to verify that the task responded to its
cancellation request.
我有一个无限循环的任务。
我有一个 CancellationToken,我将其传递给关于实际 ExecutePoll 函数的 Task.Run 调用。
我等了几秒钟然后取消令牌。
取消任务时应该 运行 有一个继续。
如果我显式调用 cancellationToken.ThrowIfCancellationRequested();,那么这个延续只有 运行s。如果我只是跳出循环,任务总是处于状态:RanToCompletion
任何人都可以分享一些关于我在这里出错的信息吗?
代码:
using System.Threading;
using System.Threading.Tasks;
namespace TaskCancellationTest
{
class Program
{
private static CancellationTokenSource _pollProcessTokenSource;
static async Task Main(string[] args)
{
InitPollingProcess();
await Task.Delay(5000);
Console.WriteLine("Cancelling loop");
_pollProcessTokenSource.Cancel();
Console.WriteLine("Loop cancelled");
Console.ReadLine();
}
private static void InitPollingProcess()
{
try
{
_pollProcessTokenSource = new CancellationTokenSource();
Task pollForListenerConfigs = Task.Run(async () =>
{
await ExecutePoll(_pollProcessTokenSource.Token);
},
_pollProcessTokenSource.Token);
pollForListenerConfigs.ContinueWith(_ =>
{
Console.WriteLine("Poll process stopped!");
}, TaskContinuationOptions.OnlyOnCanceled);
pollForListenerConfigs.ContinueWith(t =>
{
Console.WriteLine($"Task status: {t.Status}");
});
}
catch (Exception ex)
{
Console.WriteLine($"Poll process failed with Exception:\n {ex.Message}");
}
}
private static async Task ExecutePoll(CancellationToken cancellationToken)
{
while (true)
{
if (cancellationToken.IsCancellationRequested)
{
Console.WriteLine("Exit from poll loop!");
//cancellationToken.ThrowIfCancellationRequested(); // UNCOMMENT TO MAKE CONTINUATION RUN
break;
}
Console.WriteLine("Looping...");
await Task.Delay(1000);
}
}
}
}
没有错,解释的很好here:
You can terminate the operation by using one of these options:
By simply returning from the delegate. In many scenarios this is sufficient; however, a task instance that is canceled in this way transitions to the TaskStatus.RanToCompletion state, not to the TaskStatus.Canceled state.
By throwing a OperationCanceledException and passing it the token on which cancellation was requested. The preferred way to do this is to use the ThrowIfCancellationRequested method. A task that is canceled in this way transitions to the Canceled state, which the calling code can use to verify that the task responded to its cancellation request.