3

タスクを停止できません。まず、Tasks を使い始めたばかりです。以前は、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!" });
}

これで、このアクションが初めてヒットしたとき、何も起こりません。その後、2度目のキャンセル申請。今、token.IsCancellationRequested は「true」と言っているので、token.Cancel() は何かをしたに違いありません。しかし、posting.Status はまだ「実行中」です。完了するまでそのままで、その後「RunToCompletion」になります。

というわけで、Taskのキャンセルを申請したのですが、キャンセルされませんでした。

たぶん、私は何か間違ったことをしている、または明らかな何かを見逃していますが、なぜそれがキャンセルされないのかわかりません/理解できません。

多分誰かが光を当てることができますか?

よろしく。

4

2 に答える 2

7

トークンをキャンセルしても、タスクのデリゲートがすぐに実行を停止するわけではありません。それをサポートすると (Abortスレッドを介して行われるように)、オブジェクトが適切にクリーンアップされない、論理的にアトミックであることが観察されるべき操作の途中で実行が停止するために不変式が破られるなど、あらゆる種類の悪さを引き起こす可能性があります。

あなたがする必要があるのは、実行されている実際の関数に CancellationToken を見てもらい、それがキャンセルされていないことを定期的に確認することです。トークンを渡すだけでなく、それをメソッドStartNewに渡す必要があります。DoPostingそのメソッドはtoken.ThrowIfCancellationRequested();、キャンセルが実際に要求された場合に停止するのが適切なメソッド内の場所で定期的に呼び出す必要があります。

キャンセルできない非同期操作をキャンセルするにはどうすればよいですか? を参照してください。さらに読むために。

于 2013-06-06T16:29:00.073 に答える
2

おそらく、CancellationToken に期待しすぎていると思います。タスクに関しては、CancellationToken は、スロットがタスクに使用できるときにタスクを開始するかどうかを決定するときにのみ使用されると思います。タスクが開始されると、タスク フレームワークは、CancellationToken がキャンセルされたときにデリゲート呼び出しを単純に中止することはできません。このようなものを完全にキャンセルするには、タスク フレームワーク (DoPosting) によって呼び出されるコードを、CancellationToken を認識するように記述し、コード内の適切なポイントでそのトークンの状態を直接チェックする必要があります。

于 2013-06-06T16:28:57.230 に答える