I'm trying to do the following to prevent my console app do be stuck on Console.ReadLine() during termination.
await Process.GetCurrentProcess().StandardInput.WriteLineAsync();
but I'm getting the InvalidOperationException StandardIn is not redirected.
The attempt based on John's comment also fails with an exception Stream was not writable:
using (var stdInStream = Console.OpenStandardInput())
using (var stdInWriter = new StreamWriter(stdInStream))
await stdInWriter.WriteLineAsync();
Is there an easy way to achieve this?
On windows, Console.ReadLine ends up blocking on a Kernel32 ReadLine call. While there might be a way to interrupt that call and cause it to return, writing to your own input doesn't seem like the right answer.
You might be able to call CancelSynchronousIo, or just exit your own process. Neither of which is ideal.
Edit; a potentially related github issue
Related
I have a somewhat weird problem. I have a couple of DLLs that I need to use in order to write and read with an NFC reader.
This works:
LV3_InitializeSystem(5);
setAuthCode();
MessageBox.Show(""); // I immediately click and close the box
short ret = LV3_CheckIssuer();
Console.WriteLine(ret); // 0 - Success
This doesn't work:
LV3_InitializeSystem(5);
setAuthCode();
short ret = LV3_CheckIssuer();
Console.WriteLine(ret); // 90 - Card reader can not be detected.
This also doesn't work:
LV3_InitializeSystem(5);
setAuthCode();
Thread.Sleep(5000);
short ret = LV3_CheckIssuer();
Console.WriteLine(ret); // 90 - Card reader can not be detected.
I have no idea what might be the problem. I tried using threads running the initialize part with no success. How does showing a MessageBox enable the initialization to complete but Thread.Sleep() doesn't?
The DLL is apparently posting some required messages on the Windows message queue. In order for the messages to be processed, the message queue must be emptied.
One way of ensuring these messages are processed is to use Application.DoEvents(). Generally Application.DoEvents() is frowned upon - see https://blog.codinghorror.com/is-doevents-evil/ for reasons why this is.
There are other ways to solve this without using Application.DoEvents(), but it would probably require restructuring your code - for example using async/await with a Task.Delay.
Im using Stockfish game engine to power Human Vs Computer games.
Here is first part of the code:
Process _proc= new Process();
_proc.StartInfo = new ProcessStartInfo(path);
_proc.StartInfo.RedirectStandardInput = true;
_proc.StartInfo.RedirectStandardOutput = true;
_proc.StartInfo.UseShellExecute = false;
_proc.StartInfo.CreateNoWindow = true;
_proc.Start();
_proc.StandardInput.WriteLine("uci");
_proc.StandardInput.WriteLine("ucinewgame");
At this point everything is ok, but when I try to read StandardOutput something weird happens.
string result = _proc.StandardOutput.ReadToEnd();
Stockfish.exe program pops-up my application is running but code after that line is not executing. When I press pause, it points at this line:
If I use:
while (!_proc.StandardOutput.EndOfStream)
{
result += _proc.StandardOutput.ReadLine();
}
Same thing happens only at while statement. result has its full value there, all the text is written into it.
Is there any way to overcome this without async reading?
Side problem:
Since this is all part of singleton class that is used over whole ASP.NET application, i dont feel like using async reading since Im not sure how can I protect (with locking) multiple threads writing into it. Also, I dont know how to stop current thread since the processing of command can last up to 10 sec.
I don't feel like using Thread.Sleep() to constantly check for end of reading output, not elegant.
Considering side problem, how could i avoid multithread problems if async is only solution?
My threading knowledge is weak, so please have that in mind when giving thread related answers. Thank you.
The call to StandardOutput.ReadToEnd will block until this process ends. Is the goal here to read, process, and respond to various text commands from the process you spawn as you receive them?
You must approach this via asynchronous reading.
For example, you could setup a listener to Process.OutputDataReceived. Then call Process.BeginOutputReadLine to start reading. Your code will continue execution. Meanwhile, the .NET Framework will handle incoming text messages on a separate thread.
Environment - C#, .NET 4.0, WPF, VS2010
I have an app that uses a keyboard hook to detect when a combination of four keys is pressed. When this occurs it calls Configuration.Save(), which has a call to myConfigDataSet.WriteXml(myConfigFile). And then on the next line it calls App.Current.Shutdown().
About half the time it works as expected. But many times it would insert XML content right into the middle of a previously existing configuration file, resulting in corrupt data.
I was able to fix the above issue by using...
if(File.Exists(myConfigFile)) { File.Delete(myConfigFile) }
...on the line just above the call to myConfigDataSet.WriteXml(myConfigFile)
But now many times it just writes a 0KB size file. I am pretty sure that all of my problems are being caused by App.Current.Shutdown() not waiting for the call to myConfigDataSet.WriteXml(myConfigFile) to finish.
Shouldn't this call block execution until the file has been written to disk? ...apparently not!!!
As a workaround I've already tried inserting Thread.Sleep(1000) to create a 1 second delay just before App.Current.Shutdown. But now sometimes the app errors out with a "StackOverFlow" exception...!!!
What would you guys recommend as a fix or workaround for this? What am I doing wrong?
You can't stop a App.Current.Shutdown
Instead, use Application.Current.MainWindow.Close().
In this case, you can intercept in the Close event, process what you need to process, and then you could call App.Current.Shutdown
You can try to put the call to myConfigDataSet.WriteXml(myConfigFile) in a try/finally block. The finally block is executed completely even when the thread is aborted (see here). Not sure if it works with App.Current.Shutdown though.
So instead of:
myConfigDataSet.WriteXml(myConfigFile)
Do the following:
try {
// Empty...
} finally {
myConfigDataSet.WriteXml(myConfigFile)
}
I open a FileStream with FileMode.Open and FileAccess.Read. Shortly after that I call a function to handle the file's contents. I use Invoke to make the call because the call comes from a Thread and the function has to put the results on a Form. The function accepts any kind of Stream (I call it with MemoryStreams too without a problem) and uses XmlTextReader to read the XML in the FileStream, but on rare occasions for unknown reasons even the first Read() throws an ObjectDisposedException and the stream's CanRead property returns false if the stream was already closed.
In the Thread the FileStream is a local using variable, so I don't think another threads should be able to close it, and I don't close it until the Invoke returned. There are no Exceptions thrown so the file is definetly there (since there is no FileNotFoundException) and should be accessed properly (since there is no UnauthorizedAccessException and IOException).
How could my FileStream still look closed sometimes just after opened?
(It might matter that I'm running my code on a Windows CE 5 device with Compact Framework 3.5 and I wasn't able to reproduce the same behaviour on my desktop PC with XP yet.)
EDIT:
I know, that this Invoke is ugly but that alone can't be a reason to fail, can it? (And, in most of the cases it doesn't fail at all.)
//the code in the thread
//...
using (FileStream fs = File.Open(assemblyPath + "\\white.xml", FileMode.Open, FileAccess.Read))
{
mainForm.Instance.Invoke(new DataHandler(mainForm.Instance.handleData), new object[] { fs });
}
//...
//and the handler
public void handleData(Stream stream)
{
infoPanel.SuspendLayout();
try
{
using (XmlTextReader xml = new XmlTextReader(stream))
{
//it doesn't matter what is here
}
}
catch{}
}
There's one reason I can think of: the worker thread got aborted. This will run the finally block generated by the using statement and close the file. How it could be aborted is a secondary question. Is the thread's IsBackground property set to true? Is the program bombing on an unhandled exception elsewhere and shutting down? Just guesses of course.
Sure, this is expected behavior. You call Invoke, which marshals the call to another thread. The calling thread then continues to run and the using block exits, calling Dispose on the stream. This Dispose is happening before you are done (and maybe before you start) using the stream in the UI thread. The exact timing of these actions is going to depend on processor load and some other factors, but it's certainly unsafe.
Either don't put the stream in a using block or better yet have the thread do the read and pass the results to the UI via Invoke.
EDIT
As Hans points out in the comment, the above explanation should be for a BeginInvoke call, which underneath calls PostMessage. Invoke, on the other hand, uses SendMessage. Both propbably uses some WM_COPYDATA shenanigans (I've not looked to see) to marshal the data.
The Invoke call should be executing the entire handler you have posted, though the behavior you see indicates otherwise. From the code you posted there's no real way for us to determine what is closing the stream.
I would still refactor what you've done here because right now you're tying up both the UI and worker threads with the reader operation. I'd do the read work in the worker thread and then pass the results to the UI. This would decrease the odds of the reader work causing UI choppiness and would eliminate the possibility of the stream getting closed while you're reading from it.
I saw the same issue on some embedded board (ARM) I'm working on. Then I created a little test.
The following code (not involving any Threads!) crashes:
using (var w = new StreamWriter(File.Create("file.txt"), System.Text.Encoding.UTF8))
{
for (int i = 0; i < 1000; i++)
{
w.WriteLine("Test");
}
}
This code however does not crash:
using (var w = File.CreateText("file.txt"))
{
for (int i = 0; i < 1000; i++)
{
w.WriteLine("Test");
}
}
So, my guess can only be that the underlying native code treats text files differently than when you open the file using File.Create(). Both files are then written in UTF-8, so there is no difference about the encoding.
BTW: sorry I'm one year late on the answer, but I hope it'll help somebody
Not to long ago i asked about an error msg that occurred when when app.PriorityClass = ? was before app.start. Apparently the solution which i didnt like was to write it after start.
It worked without much problem until today. I get a "Cannot process request because the process has exited." exception because the process completes quickly enough to not have its priority changed (some of the time). Wrapping a try around this feels bad. What is the real solution? how do i launch a process with low priority ?
Process app = new Process();
app.StartInfo.FileName = #"bin\convert.exe";
app.StartInfo.Arguments = string.Format("{0} -resize 150x150 {1}", filename, thumbName);
//app.PriorityClass = ProcessPriorityClass.BelowNormal; //No process is associated with this object.
app.Start();
//app.PriorityClass = ProcessPriorityClass.BelowNormal; //"Cannot process request because the process has exited."
Your choices are:
Try to set it and catch the exception if it has already exited.
Check to see if the process has exited first and then try to set it ... and still catch the exception if it has already exited.
Because even when you check, the process could still exit between when you check and when you try to set it. So, really, just go with option #1 because it's less code.
The solution: start the process suspended, then change the priority, and then resume the process.
This is done in Win32 with CREATE_SUSPENDED in the call to CreateProcess, but unfortunately I don't know the .NET way offhand.
Why would you want to avoid catching and exception condition that you know how to deal with at the lowest possible level? If you can set the priority, great! If not, the process has quit and your work is done. I don't think there's any reason to try and avoid appropriately handling the error.
Any test you can do is going to immediately be a race condition; if the app exits quickly, the only safe thing I can think of is to use try/catch.
Unless it reads from stdio? In which case you could redirect it and deliberately not close the input stream until you've changed the priority.
You could always use an if statement:
if (!app.HasExited)
{
app.PriorityClass = ProcessPriorityClass.BelowNormal;
}
I agree with the other answers though, you should still be catching your exceptions and handling them properly anyways.