cancellation token to stop Console.ReadLine is only working on the first try
I have the following method I got from stackoverflow
I run it in a loop while passing it a cancellation token.. and the cancellation token is also in a loop, which means, I recreate it every time.. it works on the first try.. but after the recreation starts for the cancellation token, on
await Task.WhenAny(readTask, Task.Delay(-1, cancellationToken));
cancellation token doesn't get to end first although it should have from the other concurrent task I manage to cancel the token. What could be a possible solution? Thank you!53 Replies
Why are you passing in a negative value to a delay method?
to make the wait time indefinite until cancellation token cancels it
Cool, wasn't aware that was an option. 🙂
hehe, the problem is nnow either Task.WhenAny is doing something wrong or cancellationToken is not being hit in the delay
So, your readtask, the
var readTask
, is not passed a cancellation token. Is that intentional?
Also you are setting the throw behavior after all your code has been awaited. Is that too intentional?I am not sure as I just got the solution from the internet 😅
Okay. Let's start fresh.
What do you want to achieve? In plain english pseudocode
but I think it is okay as long as the delay is the one getting done first
while readline is awaiting, I wanna cancel the ReadLine whenever I want to
"I want an application that asynchronously reads a line from the user, that can be cancelled by a cancellation token at any point"like this you mean? So for example if a user has a time limit to type in a line, the cancellation token should cancel it after that limit? I'm just trying to understand what you want before I suggest anything
yep, that's what I meant
You're trying to cancel a synchronous operation (
Console.ReadLine
)
That's not possible in this way
Cancellation is cooperative, you can't force a method to be cancelled
You can write your own impl of that using stdin maybe
Your readTask is blocking internally via Console.ReadLine
, so even if you throw on cancellation requested, the task will still be around in the background, waiting for inputinteresting
I think you are right, I need to implement my own imp using stdin
it is just weird how it works on first try and then it doesn't
Just use
Console.In.ReadLineAsync(CancellationToken)
That one ignores the token I think
this is also not working.. I tried
Ah I see
wack
it doesn't ignore it but it doesn't cancel the readline huh
Guess you do have to write your own
(code is source for
TextReader.ReadLineAsync
This seems to work when I run it once, and is quite similar to what was originally posted
But it doesn't support the cancellation, so I'll add that in, a sec
Question could be:
Given two parallel
Console.ReadLine
calls, upon receiving input, which one gets the input?
If both do, you can do the cts approach
Also, instead of using delay, You could use a TaskCompletionSource
, create it by passing the token param and WhenAny
using thatah okay.. let me try that
Yeah I got that working, but I'm not sure this is more readable than not using the TaskCompletionSource.
it is not a big problem in my project. That's why I am delaying it a bit to fix major issues first.. sorry for the late replies
Nah I agree now, TaskCompletionSource is clean.
I'll wait for you to give this a go before I post mine @Abdesol 🙂
oh okay.. will check how I can do that
We tend to want to help you figure the goal instead of providing the entire solution. Reason being you don't really learn much if the solution is just handed to you
But now I think I'll try and implement this myself because it sounds like a cool little puzzle...
We can compare notes later lol
@TeBeCo I've been baited again
yeah... that is very much understable
@Abdesol
What is the desired bahaviour for parallel invocations of
ReadLineAsync
? Should they all receive the same input or each their own?Sorry if I was unclear. There is no parallel invocations of ReadLineAsync.. it is just parallel with another task that awaits for something to finish.. if that task is done, we raise the cancellation token, since we don't need user input
basically, what I am building is a terminal
some scripts I run with the terminal want user input.. and the read line is for user input
Yeah, problem is, you can't cancel the
ReadLine
, so if we cancel operation a, operation b will later have it's ReadLine
synchronized to the cancelled one
so we have to input something for op a
in order for op b to receive inputah, I see..]
what was the code sharing website
I want to share it here
my approach for the terminal
$paste
If your code is too long, you can post to https://paste.mod.gg/, save, and copy the link into chat for others to see your shared code!
If it is less than like 30 lines, you can just do it in here tbh
Mine, which has comments and newlines, is 19 lines
BlazeBin - qlfcrxbptnpp
A tool for sharing your source code with the world!
oh.. it is not the fix I made.. I will have to do that
I have a working implementation that I could share
It's strongly coupled to
Console
though, so no real reusabilitySo is mine, but honestly that's just an input source that can be changed
Let's share
I'm going to have to go for lunch now, but this is the approach I made:
Unknown User•7mo ago
Message Not Public
Sign In & Join Server To View
Consumer needs that
Unknown User•7mo ago
Message Not Public
Sign In & Join Server To View
https://paste.gg/p/anonymous/69d1b968e05e4bc9ae2073bdc11f8f7c
Yes, the consumer will have to
let me try this
still.. this approach works only once for me
like it is a terminal so it is in a loop
I use cts like this
so on first enter, it goes and throws error.. on second, it doesn't throw error until I click enter again
Can you share how you're invoking the method?
maybe that thing that you said, the readline from the previous one is still active
in this code I just changed
to
Yes, that is what I'm doing, we keep a single
ReadLine
-task alive for all ReadLineAsync
invocations, and when it completes it enables another ReadLine
to occuryeah it looks like that
did you try it in a loop
where cts have to be desposed and defined multiple times?
I feel like the recreation of cts is the problem here
Add a
try/catch
block for OperationCancelledException
around your usage of ReadLineAsync
When you cancel the operation, that thing is gonna throw
Instead of your catch-all
And what do you mean by "it only works once"? Does the method only return input once for all invocations?
this
works just fine for melike, it does it once and it doesn't work again
shall I put the full code on paste bin and will you try it? It is just a one page program.cs code
this also works for me.. but the cts is cancelled in another task
actually this is also not the main task
by it only works oce I mean, upon cts getting redefined, it stops working
this is the problem for me
after first try, when cts gets redefined, the issue is this
sure you can paste your code, I'll take a look at