取消任务会引发异常,但任务会继续

时间:2020-02-04 11:52:41

标签: c#

我正在尝试取消一项长期运行的任务,即模拟无限循环打印到控制台。 2秒后从主线程调用取消令牌。即使控制台上的输出显示“令牌IsCancellationRequested true”,循环仍会继续。这里有什么问题?

       private static void CancelingTasks2()
        {
            CancellationTokenSource cts = new CancellationTokenSource();
            CancellationToken token = cts.Token;
            t = Task.Factory.StartNew(() => 
            {
                if (token.IsCancellationRequested)
                    throw new OperationCanceledException("cancelled on the token", token);
                print("printing for ever ...");
            }, token);

            Thread.Sleep(2000);
                cts.Cancel();
            Console.WriteLine("canceled");
            Console.WriteLine("task status  " + t.Status);
            Console.WriteLine("token IsCancellationRequested  " + token.IsCancellationRequested);
        }

        private static void print(string txt)
        {
            while (true)
            {
                Console.WriteLine(txt); Thread.Sleep(500);
            }
        }

2 个答案:

答案 0 :(得分:1)

使用Task.Run代替Task.Factory.StartNew,并尝试避免将TaskThread.Sleep混合使用。使用Task.Delay。如果使用Task,则代码需要一直保持异步状态。

您的循环继续进行,因为没有任何事情可以中断。

使用正确的语法重写以上示例,看起来像这样

public class Program {
    public static async Task Main(string[] args) {
        Console.WriteLine("Hello");
        await CancelingTasks2();
        Console.WriteLine("Exit");
    }

    private static async Task CancelingTasks2() {
        CancellationTokenSource cts = new CancellationTokenSource();
        CancellationToken token = cts.Token;

        var t = print("printing for ever ...", token);

        await Task.Delay(2000);

        cts.Cancel();

        Console.WriteLine("canceled");
        Console.WriteLine("task status  " + t.Status);
        Console.WriteLine("token IsCancellationRequested  " + token.IsCancellationRequested);
    }

    private static async Task print(string txt, CancellationToken token) {
        while (true) {
            if (token.IsCancellationRequested)
                throw new OperationCanceledException("cancelled on the token", token);
            Console.WriteLine(txt); 
            await Task.Delay(500);
        }
    }
}

并在运行时产生以下输出

Hello
printing for ever ...
printing for ever ...
printing for ever ...
printing for ever ...
printing for ever ...
canceled
task status  WaitingForActivation
token IsCancellationRequested  True
Exit

Fiddle

答案 1 :(得分:0)

好像您在打印中进行了无限循环,没有多次检查令牌取消。

如果在while循环中,则应放置您自己:

function Display() {
    let events = new Set()
    let tabs = [];
    const [items, setItems] = useState([]);

    const getList = async () => {
      const res = await  ApiCalendar.listUpcomingEvents(10);

       setItems(res.items);
    }

    useEffect(async () => {
      getList();
    }, []);

  return items.map(item => <div>{item}</div>);
}