gpt4 book ai didi

c# - 将取消 token 提供给任务什么都不做?

转载 作者:太空宇宙 更新时间:2023-11-03 23:27:40 25 4
gpt4 key购买 nike

我有两个例子,直接来自微软,这些例子似乎与取消 token 无关,因为我可以删除提供给任务的 token ,结果是一样的。所以我的问题是:什么是取消 token ,为什么是糟糕的例子?我错过了什么..? :)

using System;
using System.Threading;
using System.Threading.Tasks;
namespace Chapter1.Threads
{
    public class Program
    {
        static void Main()
        {
            CancellationTokenSource cancellationTokenSource =
                new CancellationTokenSource();
            CancellationToken token = cancellationTokenSource.Token;
            Task task = Task.Run(() =>
            {
                while (!token.IsCancellationRequested)
                {
                    Console.Write(“*”);
                    Thread.Sleep(1000);
                }
                token.ThrowIfCancellationRequested();
            }, token);
            try
            {
             Console.WriteLine(“Press enter to stop the task”);
             Console.ReadLine();
                cancellationTokenSource.Cancel();
                task.Wait();
            }  
catch (AggregateException e)
            {
                Console.WriteLine(e.InnerExceptions[0].Message);
            }
            Console.WriteLine(“Press enter to end the application”);
            Console.ReadLine();
        }
    }
}

代码示例2: https://msdn.microsoft.com/en-us/library/system.threading.cancellationtoken(v=vs.110).aspx

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
public static void Main()
{
// Define the cancellation token.
CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;

Random rnd = new Random();
Object lockObj = new Object();

List<Task<int[]>> tasks = new List<Task<int[]>>();
TaskFactory factory = new TaskFactory(token);
for (int taskCtr = 0; taskCtr <= 10; taskCtr++) {
int iteration = taskCtr + 1;
tasks.Add(factory.StartNew( () => {
int value;
int[] values = new int[10];
for (int ctr = 1; ctr <= 10; ctr++) {
lock (lockObj) {
value = rnd.Next(0,101);
}
if (value == 0) {
source.Cancel();
Console.WriteLine("Cancelling at task {0}", iteration);
break;
}
values[ctr-1] = value;
}
return values;
}, token));

}
try {
Task<double> fTask = factory.ContinueWhenAll(tasks.ToArray(),
(results) => {
Console.WriteLine("Calculating overall mean...");
long sum = 0;
int n = 0;
foreach (var t in results) {
foreach (var r in t.Result) {
sum += r;
n++;
}
}
return sum/(double) n;
} , token);
Console.WriteLine("The mean is {0}.", fTask.Result);
}
catch (AggregateException ae) {
foreach (Exception e in ae.InnerExceptions) {
if (e is TaskCanceledException)
Console.WriteLine("Unable to compute mean: {0}",
((TaskCanceledException) e).Message);
else
Console.WriteLine("Exception: " + e.GetType().Name);
}
}
finally {
source.Dispose();
}
}
}

最佳答案

因为 .Net 中的取消是通过协作将 CancellationToken 传递到 Task.Run 中的,例如不足以确保任务被取消。

将 token 作为参数传递只会将 token 与任务相关联。只有在 token 被取消之前它没有机会开始运行它才能取消任务。例如:

var token = new CancellationToken(true); // creates a cancelled token
Task.Run(() => {}, token);

要“中途”取消任务,您需要任务本身观察 token 并在发出取消信号时抛出,类似于:

Task.Run(() => 
{
while (true)
{
token.ThrowIfCancellationRequested();
// do something
}
}, token);

此外,简单地从任务内部抛出异常只会将任务标记为Faulted。要将其标记为已取消 TaskCanceledException.CancellationToken 需要匹配传递给 Task.Run 的 token

关于c# - 将取消 token 提供给任务什么都不做?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33342481/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com