System.Diagnostics.Process.Start weird behaviour - c#

I'm writing an application to start and monitor other applications in C#. I'm using the System.Diagnostics.Process class to start applications and then monitor the applications using the Process.Responding property to poll the state of the application every 100 milisecs. I use Process.CloseMainWindow to stop the application or Process.Kill to kill it if it's not responding.
I've noticed a weird behaviour where sometimes the process object gets into a state where the responding property always returns true even when the underlying process hangs in a loop and where it doesn't respond to CloseMainWindow.
One way to reproduce it is to poll the Responding property right after starting the process instance. So for example
_process.Start();
bool responding = _process.Responding;
will reproduce the error state while
_process.Start();
Thread.Sleep(1000);
bool responding = _process.Responding;
will work.
Reducing the sleep period to 500 will introduce the error state again.
Something in calling _process.Responding too fast after starting seems to prevent the object from getting the right windows message queue handler. I guess I need to wait for _process.Start to finish doing it's asynchronous work. Is there a better way to wait for this than calling Thread.Sleep ? I'm not too confident that the 1000 ms will always be enough.

Now, I need to check this out later, but I am sure there is a method that tells the thread to wait until it is ready for input. Are you monitoring GUI processes only?
Isn't Process.WaitForInputIdle of any help to you? Or am I missing the point? :)
Update
Following a chit-chat on Twitter (or tweet-tweet?) with Mendelt I thought I should update my answer so the community is fully aware..
WaitForInputIdle will only work on applications that have a GUI.
You specify the time to wait, and the method returns a bool if the process reaches an idle state within that time frame, you can obviously use this to loop if required, or handle as appropriate.
Hope that helps :)

I think it may be better to enhance the check for _process.Responding so that you only try to stop/kill the process if the Responding property returns false for more than 5 seconds (for example).
I think you may find that quite often, applications may be "not responding" for a split second whilst they are doing more intensive processing.
I believe a more lenient approach will work better, allowing a process to be "not responding" for a short amount of time, only taking action if it is repeatedly "not responding" for several seconds (or however long you want).
Further note: The Microsoft documentation indicates that the Responding property specifically relates to the user interface, which is why a newly started process may not have it's UI responding immediately.

Thanks for the answers. This
_process.Start();
_process.WaitForInputIdle();
Seems to solve the problem. It's still strange because Responding and WaitForInputIdle should both be using the same win32 api call under the covers.
Some more background info
GUI applications have a main window with a message queue. Responding and WaitForInputIdle work by checking if the process still processes messages from this message queue. This is why they only work with GUI apps. Somehow it seems that calling Responding too fast interferes with getting the Process getting a handle to that message queue. Calling WaitForInputIdle seems to solve that problem.
I'll have to dive into reflector to see if I can make sense of this.
update
It seems that retrieving the window handle associated with the process just after starting is enough to trigger the weird behaviour. Like this:
_process.Start();
IntPtr mainWindow = _process.MainWindowHandle;
I checked with Reflector and this is what Responding does under the covers. It seems that if you get the MainWindowHandle too soon you get the wrong one and it uses this wrong handle it for the rest of the lifetime of the process or until you call Refresh();
update
Calling WaitForInputIdle() only solves the problem some of the time. Calling Refresh() everytime you read the Responding property seems to work better.

I too noticed that in a project about 2 years ago. I called .Refresh() before requesting certain prop values. IT was a trial-and-error approach to find when I needed to call .Refresh().

Related

In c#/Xamarin/Android How do I get the stack trace for all managed threads?

I'm trying to diagnose why my app is freezing up and android is displaying a message that app is not responding. For an unknown reason, messages that should show in logcat output do not when this happens.
I'm looking at using https://github.com/nwestfall/Xamarin.ANRWatchDog to find out what is going on in my app if it becomes non-responsive. The problem is, I don't see anything in call stacks from a c#/managed thread perspective.
All information I've been able to find doesn't work with c#/Xamarin/Android and/or is target the development for desktop/server development. Attempting to get a list of threads gives me a list, but all entries in the list are null. Even if I can a list of the actual threads, how do I get the call stack for each thread?
var threads = Process.GetCurrentProcess().Threads;
Is there a way to get the current stack trace for all managed threads in a Xamarin/Android app?
System.Diagnostics.StackTrace() for the current thread, however you probably don't care about that.
Here's a way to get other threads and get their stack traces:
How to get non-current thread's stacktrace?
If that doesn't work, you can certainly use a method I've used successfully in winforms, a long time ago. Here's the strategy:
ensure all your worker threads have a top-level try/catch with logging you can access
Abort the worker threads and look for the abort exceptions in the logs!
Sounds simple, but takes you straight to a crash. Still you have to get the threads to abort them, see the threadsampler.Start method first few lines in the S/O link above.
If your UI is responsive you can hide this function in an easter-egg activated devtools menu or have a debug menu activated in your configs (you'll want than when your UI apps get non trivial anyway!)
Unfortunately since it's locking up, you'll just have to start a background thread to run this functionality, you could have it ping the UI every second or 20, and abort threads if it locks. Strategy would be to invoke a 'dummy function' on the UI thread:
https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/appmodel/main-thread
and wait for it to come back, e.g., InvokeOnMainThreadAsync, it should do that in 5sec or less otherwise you take action. Apply a timeout waiting for it:
Asynchronously wait for Task<T> to complete with timeout.
Make sure to turn this off in prod!!! Or optionally, activate via switch you can direct users to turn on.
This is the pattern we used in the field for our app, years and years ago.
Full saga:
How do I get the GUI thread of winform?
A newer version of our app does all the work on a background thread and the user gets a chance to cancel if it takes more than 10 sec. However that requires the use of an abstracted UI and the team created a variation on MVVM. Useful as it allows us to deploy a thick client and web app with all the same code - including UI code. Probably not worth the effort for any other apps, and if I had to do that over I'd use javascript for a web app and deploy it to desktop in electron and mobile via cordova, react etc. Oh well.
You're probably beyond this (apologies in advance) but there is the Debug\Windows\Threads tab and if I hang a named thread deliberately in my Xamarin Android app:
new Thread(hangMe) { Name = "HangMe" }.Start();
void hangMe()
{
while(true)
{
Thread.Sleep(500);
}
}
If execution is paused by going to the VS main menu Debug\Break All then there may be some useful call stack info there in the Threads tab.
I understand that things are rarely this simple...

Application.DoEvents Never Exits

I'm working on a legacy application which has sprinklings of Application.DoEvents here and there. I'm fully aware that this is frowned upon due to re-entrancy issues, but re-factoring isn't currently an option.
An issue has started to occur where DoEvents never exits. The UI is responsive (I can see UI thread activity in the user logs) so DoEvents seems to be pumping the messages, but for some reason it never completes. Unfortunately this DoEvents is in the main data-processing component, which means this stops processing server responses as it's stuck on the DoEvents line.
We have Stopwatch trace which tells how long the DoEvents ran for - staggeringly I got a log where it said it was running for 188267770 milliseconds, which is 52 hours (gulp). It seemed to get into this state at about 3am on a Saturday, until the user came in on Monday and shut the app down (not killing the process, I can see the GUI thread trace closing things gracefully), at which point the DoEvents completes and the timer data is logged (so something which happens during shutdown must convince DoEvents to complete).
Of course, this only happens on the production user's machines, and not on my dev box :)
Has anyone ever seen a similar problem to this?
I've decompiled DoEvents and also how Conrol.BeginInvoke pushes method delegates onto the GUI thread using the Windows message queue, but I cannot see how DoEvents can get stuck like this, and keep the UI responsive.
Source control diff is also not an option since there's been around 30 versions since the last 'good' version the users had, and this new version with the problem - so about 200 files have changed.
Many thanks
Paul
For the loop to keep running there must be messages on the message queue. So I assume that there is a message that when dispatched then causes another message to be put on the queue. And so forth forever.
Do you have any background processing that causes this type of behaviour? Posting another message to continue processing? Is there an event in the system that can occur that when processed could simply occur immediately again?
The other alternative is that one of the messages is itself creating a nested message loop. For example, showing a dialog would cause a nested message loop that does not finish until the dialog is removed. Does your app try and show a dialog that will then not be dismissed for some reason?
Impossible for us to tell you the answer given the number of possibilities.
After much digging I finally found the cause - System.Windows.Forms.Timer.
Basically two or more Timers can cause a DoEvents() call to never end. Whilst processing one timer WM_TIMER message, another timer can post its WM_TIMER message, which is then processed by DoEvents, as that is being processed the first Timer will post, and so on.
The app I'm working on has about 8 Timers I've found so far....
But really, DoEvents is the real culprit so I plan to re-factor to get rid of it.

code executed too long, how to stop executing

We have C# application that crawling and executing code. But some time system stolp responding becouse code executing too long. How can we stop executing code after 10s that application will not stop responding any more.
The approaches taken to tackle this problem are dependent on the way you've designed your long running operation. So, without further details, I can only provide general pointers.
If your code takes to long to execute because you're not getting a response from a remote system (ie. db, website, etc) in time, then consider timeouts. If the API you use for making those remote calls, doesn't support timeouts, consider something like the CircuitBreaker pattern:
http://davybrion.com/blog/2009/07/protecting-your-application-from-remote-problems/
http://timross.wordpress.com/2008/02/10/implementing-the-circuit-breaker-pattern-in-c/
If it's simply that your application is doing a lot of work, make sure you do that work on a thread other than the UI thread, as Twitch said, to keep the UI responsive.
If you're using a very long loop doing internal work, then it could be worth checking repeatedly in that loop for a cancelation condition being met (this could be a flag set from a different thread or even elapsed time). This approach is called cooperative cancellation.
This article on the .Net 4.0 cancellation framework gives some good background, along with this article which it references.
You have to add some sort of way for the program to tell windows "no, it's not frozen, it's working", either by making all the processing and crawling in another thread, or by doing some form of notice, like printing something every few frames.
You can call Application.DoEvents to perform events while performing a long task in a GUI thread. That way it won't block the GUI.
You should consider running the long task in a thread itself though, since you get a lot more direct control then.

Error handling patterns for multithreaded apps using WF?

I was writing up a long, detailed question, but just scrapped it in favor of a simpler question that I didn't find an answer to here.
Brief app description:
I have a WPF app that spawns several threads, and each thread executes its own WF. What are some of the best ways to handle errors in the threads and WF that will allow user interaction from the GUI side? I definitely plan to handle any low level exceptions in the thread, because I don't want the thread to exit.
Summary of questions:
How have you implemented communication between WF and the thread that starts it? There is WorkflowTerminated, but I don't want the workflow to exit -- I need to fix the problem and let it continue. I assume the only option is using a FaultHandler, but was wondering if there's another way to do it without using an activity block. I am hoping there's a framework out there that I just haven't found yet.
The error from WF needs to get caught by the thread, which then needs to display the error in the GUI. The user will then make a logical choice for recovery, which should then be sent back to the thread, and then to WF. Again, is there something existing out there that I should take a look at?
Even buzzwords / keywords that accomplish what I am describing would be really helpful, and I can do the legwork on researching each of them. However, any additional insight is always welcome. :)
What's worked for me in multi-threaded WPF apps is to have the errant thread invoke a callback method that passes the exception and other info back to the UI thread. Callbacks can have return values, so if your thread can block while waiting for the user to respond, then that can work for you. Remember that the callback will run on the thread that calls it, so any UI updates have to be done via the control's dispatcher. You will have to decide whether all of the threads use the same callback and what kind of synchronization you'll need if there's a chance that multiple threads can throw exceptions simultaneously.
Here's how I ended up solving this problem. But first a little background info:
User clicks a button in the GUI that causes the candy packager to start running. This is done via a command binding in the ViewModel, which then calls a low-level function in the Model. The function in the model launches a thread and executes a state machine.
At some point, the machine will fail. When it does, I compile information about the error and possible (known) recovery methods. I put this into an object and then pass it to the GUI via a callback interface. In the meantime, the worker thread is stuck waiting for an Event to get set.
Eventually, the candy worker will notice the error and will click a button telling the system what to do. This results in two things: 1) it flags one of the recovery methods as the preferred one, and 2) sets the event. Now the worker thread continues on, checks for the preferred error recovery method and transitions into the respective state in the state machine.
This works very well (so far). The part I know is totally lame is the manner in which it checks for the preferred error recovery method. I am essentially setting a string variable, and then comparing this string to a list of known strings. Ultra lame, but I'm not sure of a better way to do this, other than using an enum. Does anyone have recommendations for me?

How to detect when main thread terminates?

What I need to know:
I would like to detect when a the main thread (process?) terminates so that I can ensure certain actions are performed before it is terminated.
What I have found myself:
I found the events AppDomain.DomainUnload and AppDomain.ProcessExit. AppDomain.DomainUnload seems to work with non-applications like MbUnit. AppDomain.ProcessExit seems to work with applications but there is a 3 second time limit which I really don't like. Is there more ways to detect when an AppDomain / process terminates?
Background:
I am looking for such an event to ensure my log is persistet to file when the application terminates. The actual logging runs on another thread using a producer-consumer pattern where it is very likely that log entries might queue up in memory and I need to ensure this queue is saved to file when the application terminates.
Is there anything else I should be aware of?
Update:
Changed the above to reflect what I have found out myself. I am not happy with the 3 second time limit during ProcessExit. The MSDN documentation does say though that it can be extended:
The total execution time of all
ProcessExit event handlers is limited,
just as the total execution time of
all finalizers is limited at process
shutdown. The default is three
seconds, which can be overridden by an
unmanaged host.
Does anyone know how to override the default?
More ideas are also highly appreciated!
Follow up:
I have posted a follow up question to this.
You should have an entry point for your application. Normally you can do there some logging when all tasks are terminated:
static void Main()
{
try
{
Application.Run( .... );
}
finally
{
// logging ...
}
}
What exactly do you want to find out?
When the process terminates? (Just because the AppDomain is unloaded doesn't necessarily mean that the entire process is terminating)
When the main thread terminates (If there are other non-background threads, the main thread can terminate without the process terminating (or AppDomain unloading)
So they're not quite the same thing.
Anyway, it is generally dangerous to have log messages buffered in memory at all. What happens if someone turns off the power? Or if I terminate your process through Task Manager? All your log messages are gone. So often, you'll want unbuffered writes in your log, to get messages pushed to disk immediately.
Anyway, another (more robust) approach might be to run the logger itself in a non-background thread. That way, even if the rest of the application terminates, the logger won't, so the process is kept alive. Then you just have to set some flag when the rest of the app terminates, to let the logger know that it too should close once it has written out all pending log messages.
It still won't save you from the case where the system loses power or someone forcibly termianates the process on the OS-level, but it will handle all cases where the application closes normally, and gives you unlimited time to perform clean-up actions (since the process isn't actually terminating yet, it's still got one live thread)
ie. guaranteed to be called and have unlimited time to finish?
Unfortunately, NO option is going to have unlimited time, and be guaranteed. There is no way to enforce this, as many things can happen. Somebody tripping over the power cord or a forced termination of your program will prevent any option from giving you adequate time to handle things.
In general, putting your logic at the end of the Main routine is probably the most reasonable option, since that gives you complete freedom in handling your termination events. You have no time constraints there, and can have the processing take as much time as needed.
There are no guarantees that this will run, though, since a forceful termination of your program may bypass this entirely.
Based on the documentation, it looks like the default application domain (the one your Main method is probably running in) will not receive the DomainUnload event.
I don't know a built-in event that would do what you expect.
You could define your own custom event, have interested parties register with it, and fire off the event just before you return from Main().
I don't know how old this thread is, but I've had a similar problem whcih was a little tough for me to solve.
I had a WinForms application that was not firing any of the above forementioned events when a user logged out. Wraaping the Application.Run() in a try finally didn't work either.
Now to get around this you would have to using PInvoke into Win32 API's to achieve this. Well you did prior to .NET 2.0 anyways. Luckly MS introduced a new class called SystemEvents. With this class you can catch a SessionEnd event. This event allows you to cleanup when the OS want to terminate your app. There is no .NET time limit o this event it appears, although the OS will eventually kill your app if you take too long. This is a little more than 3 seconds, although 3 seconds should be plenty of time to cleanup.
Secondly my other problem was I wanted my worker thread to terminate the main thread once it was finished its work. With an Application.Run() this was hard to achieve. What I ended up doing was calling Application.Run() with a shared Application context. The thread is then able to call ApplicationContext.ThreadExit() to force the Application.Run to return. This seems to work quite nicely.
Hope this helps someone.
Regards
NozFX

Categories

Resources