Why does the OnlyOnCanceled continuation get called?

元气小坏坏 提交于 2021-02-05 07:23:10

问题


When calling await RunAsync(); on the below code, I would expect the continuation with TaskContinuationOptions.OnlyRanToCompletion continuation to run, however the OnlyOnCanceled continuation gets called (yielding the debug output "Task canceled").

Why?

private static async Task RunAsync()
{
    try
    {
        await Task.Run(() => DoWork())
            .ContinueWith(
                (t) =>
                {
                    if (t?.Exception != null)
                    {
                        throw t.Exception;
                    }
                }, TaskContinuationOptions.OnlyOnFaulted
            ).ContinueWith(
                (t) =>
                {
                    Debug.WriteLine("Task canceled.");
                }, TaskContinuationOptions.OnlyOnCanceled
            ).ContinueWith(
                (t) =>
                {
                    Debug.WriteLine("Task completed.");
                }, TaskContinuationOptions.OnlyOnRanToCompletion);

    }
    catch (Exception ex)
    {
        Debug.WriteLine(ex.Message);
    }
}

private static void DoWork()
{
    Thread.Sleep(1000);

}

回答1:


You're binding your continuations wrong.

Instead of adding three continuations to the "main" task, you're adding a continuation to a continuation to a continuation. When the main tasks finishes without error, the OnlyOnFaulted continuation gets cancelled, which triggers the OnlyOnCanceled continuation you incorrectly wired to the OnlyOnFaulted continuation instead of the main task. And then the best part - this means that the second continuation finished correctly, and since you wired your last continuation on the second continuation, the final continuation runs as well, so the full output is "Task canceled. Task completed." :)

It's not obvious what you're expecting to be the correct output, though. Why are you using continuations in the first place? await handles that for you much more nicely than you can ever do manually. Mixing await and ContinueWith is rarely a good idea :) Are you trying to await the main task (failing when an exception is thrown)? Or one of the continuations? Or just the OnlyOnRanToCompletion continuation (that's what you're doing right now, and it's never going to work the way you expect it to work)? What if that continuation never gets a chance to run?



来源:https://stackoverflow.com/questions/37567142/why-does-the-onlyoncanceled-continuation-get-called

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!