Skip to content

Addressed extra Read() when task was completed #125

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

MarkMichaelis
Copy link
Member

Added an ConsoleReadAsync() method but would appreciate a second pair of eyes on the implementation. The purpose of the method is to provide a way to simulate cancelling a console.Read().

@MarkMichaelis MarkMichaelis requested a review from Keboo April 18, 2020 18:05
@MarkMichaelis MarkMichaelis assigned Keboo and unassigned Keboo Apr 18, 2020
cts.Cancel();
try { task.Wait(); }
catch (AggregateException exception)
await task;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the task is cancelled you cannot await it. Consider this example:

using var cts = new CancellationTokenSource();
var token = cts.Token;
cts.Cancel();
var t = Task.FromCanceled(token);
await t.ConfigureAwait(false);

Copy link
Member Author

@MarkMichaelis MarkMichaelis Apr 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Keboo: Are you suggesting this because I didn't await the cancelTask?
I do await task intentionally, knowing that if it is cancelled it will throw an exception.
It isn't clear what the Task.FromCanceled(token) gives me in this case.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because you call cts.Cancel just above this, doesn't that always mean this will throw?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the discussion @Keboo .

Firstly, the code has changed significantly such that the comment may no longer apply. Here's the updated code:

            try
            {
                Task.WaitAny(task, cancelTask);
                // Cancel whichever task has not finished.
                cts.Cancel();
                await task;

                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("\nCompleted successfully");

            }
            catch (OperationCanceledException taskCanceledException)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine(
                    $"\nCancelled: { taskCanceledException.Message }");
            }
            finally
            {
                Console.ForegroundColor = originalColor;
            }

Awaiting a cancelled task will indeed throw, and I count on this in order to display the cancelled message when the user cancels the activity.

Perhaps the issue is that I don't ever await the cancelTask? If I did await cancelTask I would always catch and suppress the exception because if task runs to completion, I have to cancel the cancelTask rather than continue waiting for a keyboard entry.

Is it necessary to always await all tasks even if you know they have completed and you don't care about capturing the exception?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It just seems like you are then using exceptions for control flow (something discouraged in earlier chapters). If the goal is to simply display a message, wouldn't it be better to simply check the state of the token, and display the message?
Manually setting up a continuation on the task would also seem like a preferable options to the exception handler.

@MarkMichaelis MarkMichaelis merged commit 23813d0 into Chapter19SpliNoResequenceOfListings Apr 19, 2020
cts.Cancel();
try { task.Wait(); }
catch (AggregateException exception)
await task;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It just seems like you are then using exceptions for control flow (something discouraged in earlier chapters). If the goal is to simply display a message, wouldn't it be better to simply check the state of the token, and display the message?
Manually setting up a continuation on the task would also seem like a preferable options to the exception handler.

@MarkMichaelis
Copy link
Member Author

@Keboo, that is a great point. In this case the purpose of using exceptions is to demonstrate how control flows during cancellation. To not do so would be to miss the point that invoking cts.Cancel() throws and exception and how to catch it.
Thanks again so much for the feedback. It is hugely valuable. Each an every comment you make has caused me to think/review, make a change or a clarification. Thanks so much!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants