簡體   English   中英

無法通過CancellationTokenSource.Cancel()取消任務

[英]Cannot cancel a task via CancellationTokenSource.Cancel()

我無法阻止任務。 首先,我剛開始使用任務。 以前,我一直在使用delegate.BeginInvoke()在后台運行,但這次我需要停止后台執行,如果需要的話。 所以我切換到了任務。 這是我的代碼:

CancellationTokenSource token = new CancellationTokenSource();
Task posting = Task.Factory.StartNew(() => DoPosting(docs, session), token.Token);
HttpRuntime.Cache[session.ToString() + "_token"] = token;
HttpRuntime.Cache[session.ToString() + "_task"] = posting;

這是ASP.NET MVC,所以我在HttpRuntime.Cache中存儲了持久的東西。 用戶可以通過此操作取消操作:

public JsonResult StopPosting(string session)
{
    CancellationTokenSource token = (CancellationTokenSource)HttpRuntime.Cache.Get(session.ToString() + "_token");
    Task posting = (Task)HttpRuntime.Cache[session.ToString() + "_task"];
    token.Cancel();

    return Json(new { Message = "Stopped!" });
}

現在,當這個動作第一次被擊中時,沒有任何反應。 然后我第二次要求取消。 現在,token.IsCancellationRequested說“true”,所以token.Cancel()必須做一些事情。 但是發布.Status仍然是“正在運行”。 它會保持這種狀態直到它完成,然后它是“RunToCompletion”。

所以,我要求取消任務,但它沒有被取消。

也許我做錯了什么或者我錯過了一些明顯的東西,但我無法看到/理解為什么它不會取消。

也許有人可以解釋一下?

問候。

取消令牌不會立即導致任務的委托在正確的位置停止執行。 支持(通過線程Abort通過線程完成)可能會導致各種不良,包括未正確清理的對象,由於執行停止,因為執行在邏輯上被認為是原子的操作,等等而違反不變量,等等。

你需要做的是讓正在執行的函數看看CancellationToken並定期驗證它是否還沒有被取消。 除了將令牌傳遞給StartNew您還需要將其傳遞給DoPosting方法。 然后該方法需要定期調用token.ThrowIfCancellationRequested(); 如果確實要求取消,那么在該方法中適當停止的地方。

請參閱如何取消不可取消的異步操作? 進一步閱讀。

我想你可能期待過多的CancellationToken。 關於任務,我認為CancellationToken僅在確定當任務的插槽可用時是否啟動任務時使用。 任務啟動后,任務框架不能簡單地在取消CancellationToken時中止委托調用。 為了完全取消這樣的事情,必須編寫Task框架(DoPosting)調用的代碼以了解CancellationToken,並且必須直接在代碼中的適當位置檢查該令牌的狀態。

暫無
暫無

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

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