52 Replies
https://paste.md-5.net/ipewadetam.cs
for clarity
uhh
you mean you want to move AWAY from
async
/await
?
any particular reason?I want to move into async await
Since this apparently isn't it from what I've seen
uhh
no
Because this deadlocks
you are using
async
/await
now THAT is a different story
let's see, what's the intention here?For it not to deadlock; Online I've seen it be said that I need to use
BeginOutputReads
and BeginErrorReads
, which fire events every time that there's a new stdout/stderr to be read. However, I have no idea if I could have the same logic as I have up there with events.I mean
Anddd everyone was calling THAT async, so i got confused lol
"async" and
async
/await
are not the same thing
async
/await
is a type of "async" programming
in any case
what I mean is
what is the intention of your code
what are you trying to doWhen reading stderr, I'm trying to check if anything at all is written to it, and if so, log it and return so the method doesn't continue.
Then it moves onto reading STDOUT, which just logs everything until it finds the word "Done" in there, and then it kills the process because it's not needed anymore
so, I'll assume
proc
is a Process
?The issues that can arise from STDERR happen at the start so yeah there's no need to keep checking
Yep
you've started up an external process, and told it run
and you want to read from it
yeah
where does the "deadlock" occur?
By redirecting both STDOUT and STDERR, the internal buffer of the process gets filled, and then when we read anything it tries to write into it, and causes a deadlock because it'll wait for it to be free before anything else
It's documented on MSDN as a known issue, and recommends using BeginOutputReads + ErrorReads
ah, okay
well, there's a decent chance that's what the
async
methods are using under the hood
so, it's a deadlock within the external process?Yep. It'll lock until the buffer is somehow unfilled (Which it never won't because the program is frozen)
and by consequence... We won't be able to read from it
the buffer that the process is writing STDOUT and STDERR to
So we won't go through with the program
And ours will hang too
and reading from STDOUT and STDERR by the parent process requires calling into the child process
I feel like you might be misunderstanding the issue
er
the MSDN recommendation
it's not the fault of the parent process to change how it calls into the child process to read those buffers
it's the fault of the child process for deadlocking
I.E.
it's the child process that should be implementing a way to read the buffers that doesn't deadlock
by, say, having a separate thread for console I/O
the main thread that's trying to write to those buffers can block until there's some space, but it should be a separate thread that is responsible for reading from them
got a link?
Yeah that would be neat in a perfect world but the stuff that I'm trying to run does it in the same thread, so it's up to me to go around it
To?
the MSDN documentation
like, if the child process is trying to use the same thread for both reading and writing those buffers, I don't think there's a damn thing the parent process can do except "try your best to read from the child process fast enough that the buffers don't fill up"
Ahh okay
A sec
ProcessStartInfo.RedirectStandardOutput Property (System.Diagnostics)
Gets or sets a value that indicates whether the textual output of an application is written to the StandardOutput stream.
That's probably why they tell you to use BeginOutputReads then, it just reads it instantly
But I can't return my method from an event can I?
alrighty, so this is something that you're doing within the parent?
you're redirecting the child's output into a stream you can read from?
Can i change variables that my method has access to from the events?
Nope, I'm currently doing as described above
but, like
so, you're currently creating the child process with
RedirectStandardOutput = false
?
surely not, right?
that's required for the parent to be able to read from the child at all, right?Nope, it's set to true
The issue isn't there, it's just on the deadlock
okay, cool
This would probably solve my entire thing to be fair
But its weird
I really have no idea what that means
what events?
BeginOutputReads and BeginErrorReads assign methods to be executed with every new line that appears
Oj either stderr or stdout
okay
alright, so
you're launching this child process and you want to read from both STDOUT and STDERR
you want to terminate the process early if it has any errors, yes?
after logging those
you also want to terminate the process early as soon as you see "Done" in the output
Correct
so, this isn't about deadlocking or asynchronism
it's about parallelism
you need to be doing two things at once: listening for data on two streams, and be able to respond accordingly, when some input is received
I was reading it synchronously and not in parallel, so it was deadlocking
If the issue can be solved with doing things in parallel, yep.
That's probably what BeginOutputReads does
yeah, sort of
if you were going to set both
BeginOutputReads
and BeginErrorReads
at the same time, then yeah
there really isn't any deadlock that I see in your little snippet
unless there's a .WaitForExit() call that's not shown
I feel like this could be a bit simpler, but I might just be too tired to think it through
functionally, this is about what you want
although, I am making a couple assumptions about how the STD I/O streams work
mainly, that they should close when you manually terminate a process
if not, you might need to toss in a CancellationTokenSource
that you can use to manually cancel whichever read doesn't complete first
also, like, you probably want some null-checks and stuff in there
like, on the ReadLine()
calls
the non-async
/await
version of this would look something like
or, actually
this ought to work too
although, I would guess that this might throw an exception out of .ReadLine()
if the error handler calls process.Terminate()
Whilst search of solutions I actually stumbled upon something similar, and it still hangs on
process.StandardOutput.ReadAllLinesAsync()
and the other one. I am not really able to explain very well why but it does. To be fair I probably didn't explain how the process hangs properly but oh wellif it does hang, it's because
process.StandardOutput
doesn't close itself when you manually terminate the processHow would I differentiate between termination from ErrorDataReceived and OutputDataReceived?
which doesn't really make any sense to me
¯\_(ツ)_/¯
however you like
they're 2 different events and you have complete control over them
Would this work? I'm not sure if you can just do it like that
other than the fact that
1
and 0
are not string
, sureyeah, I haven't had my coffee yet
Oh, so events declared in that way run within the scope? nice
Well then, thank you!
anonymous delegates can capture items from the scope, yes
it's called a Closure
the compiler takes care of it all for you
it creates an anonymous class to contain both the method and whatever values are captured, and rewrites your code to create an instance of that class instead of the relevant variables
ahh i see
thank you!
Was this issue resolved? If so, run
/close
- otherwise I will mark this as stale and this post will be archived until there is new activity.