見出し画像

【C#】async / Taskの中断

Task.Stop()みたいなのがあるかと思ったけど、無いんですね。

調べたらこちらでばっちり説明されてました。

private void Start()
{
    var tokenSource = new CancellationTokenSource();
    var token = tokenSource.Token;

    Task.Run(() => HeavyMethod(token));

    tokenSource.Cancel();
}

void HeavyMethod(CancellationToken token)
{
    var i = 0;
    while (true)
    {
        Debug.WriteLine(i++);
        Thread.Sleep(100);

        if (token.IsCancellationRequested) break;

    }
}

「CancellationTokenSourceからCancellationTokenを作ってTask内で自前で判定する」

のがお作法みたいです。CancellationTokenSourceは非同期メソッドが大体受け付けてるようで既存のメソッドにも使えます。Task.Run()自体も受け付けていて第2引数で渡せます。

Task.Run(() => HeavyMethod(token), token);

元のコードではDebug.WriteLine(i++);が一度呼ばれ0が出力されていましたが、こうするとHeavyMethod()を呼ぶ前にTask.Run()内でトークンを見るようでなにも出力されなくなりました。

キャンセル時のコールバック登録

CancellationTokenにキャンセル時のコールバックを登録できます。

private void Start()
{
    var tokenSource = new CancellationTokenSource();
    var token = tokenSource.Token;
    token.Register(() => Debug.Write("canceled"));

    Task.Run(() => HeavyMethod(token), token);

    tokenSource.Cancel();
}

Register()が返すCancellationTokenRegistrationはIDisposableでコールバックの有効期限を制御できます。

using (token.Register(() => Debug.Write("canceled")))
{
    Task.Run(() => HeavyMethod(token), token);
}

このようにするとtokenSource.Cancel()の前にCancellationTokenRegistration.Dispose()が呼ばれ”canceled"の出力が出なくなります。

もしお役に立ちましたらスキ(♡マーク)をお願いします!!! noteアカウントがなくても大丈夫です。サポートもお待ちしています!