簡體   English   中英

C#異步任務取消

[英]c# async task cancellation

我在掌握任務和取消令牌方面遇到一些問題。 我制作了一個程序,如下所示:

static void Main(string[] args)
{

    CancellationTokenSource token = new CancellationTokenSource();
    Stopwatch stop = new Stopwatch();
    stop.Start();

    for (int i = 0; i < 5; i++)
    {
        //Thread.Sleep(1000);
        Task.Factory.StartNew(() => myLongTask(token.Token, (i + 1) * 1000));
    }
    while (true)
    {
        Thread.SpinWait(1000);
        if (stop.ElapsedMilliseconds > 3000)
        {
            token.Cancel();
        }
    }
}

public static void myLongTask(CancellationToken token, int time)
{
    if (token.IsCancellationRequested)
    {
        Console.WriteLine("Cancelled");
        return;
    }
    var sw = Stopwatch.StartNew();
    Console.WriteLine($"Task {time / 1000} started");
    while (sw.ElapsedMilliseconds < time)
        Thread.SpinWait(1000);
    Console.WriteLine($"Task {time / 1000} ended");

}

我同時運行5個任務(盡管當我不包括Thread.Sleep()for循環似乎在任務開始之前就已經運行了?)。 當我運行程序時,所有任務都不會被取消。 另外困擾我的是...我在調用token.Cancel()時實際上取消了什么任務? 如何選擇要殺死的5個任務中的哪一個? 我可以通過任務的變量來定義每個任務,但是由於它是由CancellationToken觸發的,因此無法訪問其CancellationRequested屬性。 那我需要5個不同的令牌嗎?

當我運行程序時,所有任務都不會被取消。

那是因為您只在任務開始時檢查取消令牌。 一旦超過了第一個令牌token.IsCancellationRequested檢查,取消令牌將無濟於事。 如果將支票移入循環,如下所示:

while (sw.ElapsedMilliseconds < time)
{
    if (token.IsCancellationRequested)
    {
        Console.WriteLine("Cancelled");
        return;
    }
    Thread.SpinWait(1000);
}

...然后您將看到任務做出適當的反應。

另外困擾我的是...我在調用token.Cancel()時實際上取消了什么任務?

您不是要取消任務,而是要取消取消令牌。 任何觀察到取消令牌的任務都將被取消(或完成,或采取任何行動),但是任務和令牌之間沒有直接關聯。

當我們談論“取消任務”時,我們的意思是“取消我們認為任務正在觀察的令牌”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM