MonoMac window closing without error - c#

I'm just starting out with MonoMac in Xamarin Studio, and I've run into the strangest problem:
I a window with an NSButton and a NSTextField on it. By this point I've cut out the event handler on the button, so it doesn't DO anything, except highlight when I click it. The button creation code looks like this:
nsButton = new NSButton(new System.Drawing.RectangleF(0, 0, 100, 100));
nsButton.BezelStyle = NSBezelStyle.RoundRect;
nsButton.Font = NSFont.SystemFontOfSize(
NSFont.SystemFontSizeForControlSize(NSControlSize.Regular));
nsButton.StringValue = text;
...and then it gets added to the window like so:
nsView.AddSubview(control.Handle as NSView);
(because in this part of the code, control.Handle is typed as object, and nsView is the main view on the window).
All runs and works fine at first. But, if I click repeatedly on that button, eventually the window just closes. No error, no exception, and the app itself doesn't quit; menus continue to respond and cheerfully log messages when I use them. But the window is simply -- gone.
It's extremely repeatable: it happens after 21 clicks. If I add an event handler that updates the NSTextField (e.g. hello.Caption="Foo";), then it happens after 19 clicks. It doesn't matter whether I click fast or slow; it's always the same number of clicks. Note that there is no code in the project to close the window, and the window doesn't even have a close box; I know of no legitimate way to close it short of quitting the app.
I am baffled here, and don't know how to debug this further. Does Xamarin have some sort of evaluation limit that closes your windows after so-many events? Is it a framework bug? Any insight will be greatly appreciated.

But, if I click repeatedly on that button, eventually the window just
closes. No error, no exception, and the app itself doesn't quit; menus
continue to respond and cheerfully log messages when I use them. But
the window is simply -- gone.
This "disappearing without a trace" sometimes occurs when an application crashes in native code badly enough. This can occur due to bugs in the binding code or mistakes made in calling the native APIs that corrupt internal cocoa state. I believe you are using MonoMac, and that this particular issue has been fixed in Xamarin.Mac.
You can sometimes get more information from the output window or by attaching lldb to your process.

This turned out to be the same issue as this one, in a slightly different guise.
In short, I wasn't keeping a reference to the NSWindow object, but instead was letting it go out of scope. So the GUI window would stick around for a while, but eventually (after some number of events or other code creating behind-the-scenes garbage) it is noticed and disposed of by the garbage collector. The window is then torn down.
It's all perfectly reasonable once you think of it, and happens under both Xamarin and MonoMac (just at slightly different times).
The simple solution, of course, is to retain a reference to the window until you're truly done with it. Problem solved!
(And yes, I feel a bit sheepish, but hopefully this question will get found by future Mac C# developers, and save them some grief.)

Related

Debug not stopping after form closing in Visual Studio

Visual Studio Debug does not stop when i close the form that i write in C#. How can i stop debug process when i close form. I added Application.Exit() method in the form closing event but it didn't work.
Thank you.
Try this from here
If (System.Windows.Forms.Application.MessageLoop)
{
// Use this since we are a WinForms app
System.Windows.Forms.Application.Exit()
}
Else
{
// Use this since we are a console app
System.Environment.Exit(1)
}
EDIT:
If there are running infinite threads then do
Thread myThread = new Thread(...);
myThread.IsBackground = true; //set your running thread to background
myThread.Start(...);
And you can see how to? from here
Well this will be four years too late, however, I thought I'd post this for anyone else who runs into this issue (like I just did), sorry in advance if this is pretty basic, I'm fairly new to C# so this threw me for a bit.
I had the same issue as OP where, in my FormClosing event, neither Application.Exit() or Environment.Exit(0) would end the debugger.
The thing I found was looking at the reference count above my FormClosing event, it was showing '0 references'. I had just copied and pasted the closing event from another forum so there was no event handler to actually handle the event I had created/copied.
One easy way to resolve this (besides not copy and pasting code) was to create the event handler:
First go to the 'Form1.cs [Design]' tab
Navigate to the 'Properties' box
Click on 'Events'
Find 'FormClosing' and double click that
If you had the same issue you should now be able to see that there is at least 1 reference to the event. Now when you close the form it should also stop the debugger.
I landed on this question because VS was not stopping when a debugged application was shut down.
One way to see what might be causing the ide to hang is to click on pause and on the 'Debug Location' toolbar view any threads that are still running. For me I noticed that there was still a RabbitMq context that was not disposed of. So this was the clue i needed.
After I made the code change, VS now stops it debugging session once the application exits.
I know this is not a solution that you might be expecting but finding out why applications are not exiting properly or still keeping background processes alive is a very tricky subject. The active threads drop down is the best place to look imho.
Another possibility is, that your process runs in an exception which isn´t handled correctly. I used to show exception messages in self-build dialogs, but forgot to show the created window in one case. So the program ran into the exception, created the window but just didn´t show any sign of it... so the process kept running even when I closed the application.

Window emitting a sound when I try to restore it from the taskbar

I'm working on a rather big project with my team and after a while, we struck into a big problem.
Infact when we minimize the main window of the application, clicking on the taskbar to restore it results in a "bing" sound (the one that windows uses when you are trying to interact with a background window when a modal dialog is opened on it). I can't restore the window except if I press ENTER button (after obviusly clicking on it).
We are using XNA to render something inside a WindowsFormsHost component in our WPF application and the problem comes out when we change something that is not connected directly with wpf (something inside the rendering engine, so it works only with XNA).
I can't post any code because I don't own any rights of it and would be meaningless because the project is enough big.
So my question is: what are the things that can produce a problem like this one (unable to restore window sound) when you click on the taskbar?
At least I can understand where to search for this bug, because I don't even understand where I shall dirt my hands in.
Important notes: I'm using a splash screen and the problems come up when I do something on a second window (so not directly the main one) which is not modal
Thanks for any suggestion
We solved the problem by finding out that there is a bug with an external component that we used inside our application. Still I don't understand how this bug has been created, if someone has a better answer I'll mark it.

Winforms application stops drawing but remains reactive to events

We have a C# .NET 3.5 UI client application that runs in a multiple monitor desktop environment (typically 4 screens) on Windows 7. Every so often, after running several of these applications, the screen stops redrawing.
Controls continue to be reactive to clicks or keypress and values can be updated programmatically, but the entire form is not redrawn to reflect any changes. For example buttons that are enabled/disabled based on state may be remain grayed out, but be reactive to clicks or vice versa. Buttons do not animate when clicked.
Workaround: minimizing and restoring the window appears to clear the problem. After this, the application begins to draw correctly.
The must frustrating aspect of this problem is that programmatically, everything appears to be running normally. No exceptions are caught in our logs. Nothing was visible in the system event logs. We have not found a way to detect this condition is happening yet.
Other miscellaneous aspects: logging uses log4net, server communication layer uses ZMQ
Update:
Calling form Invalidate() and Update() does not fix the problem.
When dragging the window between screens, it shows different values on each screen.
Minimize/restore still resolves the issue.
I can't be sure of anything without seeing the app and the code, but my best guess is someone calls .SuspendLayout() before a complicated update, and an exception (probably swallowed) prevents the code from ever reaching the corresponding .ResumeLayout(). To test this, try adding a button that calls .ResumeLayout() for the form.
It seems the solution is there:
1) http://blogs.msdn.com/b/alejacma/archive/2009/08/11/controls-won-t-get-resized-once-the-nesting-hierarchy-of-windows-exceeds-a-certain-depth-x64.aspx
2) http://support.microsoft.com/kb/2664641/en-us

Small flickering when showing a modal dialog in .NET

I'm experiencing a annoying issue in my .NET Windows Forms application.
I have a MainForm (A) and a progress form (B) that is shown modal when I start a long operation.
When the operation finishes, and B is closed, it seems that the window that is behind my application (is occurs usually with Skype) is brought to front during few milliseconds and, then my application is activated normally.
Is only a small flickering, but annoying. Here I write some tips that could help to find the solution:
I called showDialog without IWin32Window, but I added it without success result.
I closed B using Close(), then I tried Hide() and then Close() but did not help.
The code that executes the ShowDialog() is invoked from the UI thread, so it don't seem to be a threading issue.
Any clue would be appreciated. Thanks in advance.
I was experiencing these same symptoms and it was driving me crazy.
I finally discovered the problem was that i was calling this.Dispose() instead of this.Close() to close the modal window I'm not sure why I called this.Dispose() in the first place.
After switching methods, the problem went away.
I realize that this thread is old and this is not the cause of your problem, i am just trying to help anyone else who made the same mistake that I did.
Check if you DON'T call Hide or Close. The only way to avoid flickering is DialogResult.
Upd:
this.DialogResult = DialogResult.Ok
Check handlers OnFormClosing and etc. They might containt wrong method call.
The little trick is to set Owner explicitly
_dialog.Owner = this;
_dialog.ShowDialog();
People who are editing the post - _dialog.ShowDialog(this) works a bit different.
Look at owner = ((Control) owner).TopLevelControlInternal; in decompiled code
Edited by someone:
Or...
_dialog.ShowDialog(this);
These calls are identical according to MSDN
Do not call Close for modal window (it will not be disposed and memory leak is guaranteed)
Set this.DialogResult = DialogResult.OK
Call Dispose() from the parent, NEVER from the form you are closing
Remember of disposing all of your components holding by the form IContainer in Dispose(bool) (VS Designer implementation of Dispose(bool) is usually not enough not to have memory leaks)
In my case I was also facing the same issue in my VB.Net winform application but a bit different scenario.
I was having a user control which opens up a dialog using showdialog() say dialog1 and on filling some data it hides dialog1 and opens up dialog2 using showdialog() again.
In the process of hiding dialog1 and showing dialog2 flickering occurs and it shows the window at background for a moment.
After trying so many solutions and workarounds none work for me. I found one workaround myself which might help others.
To hide dialog1 I was using Me.Hide(), The solution is to change the opacity of form instead of calling Hide() method.
'Me.Hide()
Me.Opacity = 0
After this workaround the application works fine without any flickering issue.
PS: The above code lines are in VB.Net but enough for a .Net winform application developer to get the idea for fixing this issue.
Okay,
it sounds like
In the main window a user starts a long operation
You display a progress modal window
Operation completes you close the progress window
Your main window doesn't display immediately. Instead something behind it shows through for a second or less.
Your main window completes it's redraw operation and is 100% visible.
This happens more often when you have applications such as Skype running.
If that's the case there are many different possible causes. For example, your video drivers might have a bug in them causing delays in off screen compositing under certain conditions.
The system itself might even be experiencing a blocking CPU operation at the moment. This is something that could be caused by the time it takes your code to close the dialog and go back to the main form. You might look to see if there is anything else you are doing between the time the progress closes and you return UI control back to the user.
The system might simply be memory constrained and your operation causes a huge swap to disk. When the operation completes, windows might be notified that it needs to pull previously swapped memory from disk and shove it back into RAM, causing a delay.
I'd run the app with Nothing else loaded but task manager or resource monitor and see what happens. If the problem no longer occurs, then look into adding more RAM to your machine and/or ignore it.
If it's still occuring, and your memory usage leaves nearly nothing left then, again, add RAM or ignore.
If it's still occuring but memory usage is low, investigate your code to see what you are doing between the closing of the dialog and release of control of the main window back to the user.
You could try double buffering your form with this example:
Tends to eliminate flicker on screen updates.

Animated gif on button stops after moving (redrawing) the form

I have an animated gif placed on the button. It's animating ok (most of the times :P) but when the windows is redrawn (repainted) the animation stops. I have tried to refresh the button (button.Refresh() ) while handling Paint event but it didn't solve the issue. \
Anyone knows how to fix this?
Perhaps I am mistaken, but I think the issue is that it stops animating not when the form is redrawn, but when the animated object is obscured by another window. This is intended behavior; the bug is that in Windows Vista and Windows 7, the display is composited, so even though the window was 'obscured' it was never truly obscured, and it will never receive paint messages when un-obscured which will kick the animation back in.
This bug appears to affect any ButtonBase-derived control with an animated object.
The issue is the Control.IsWindowObscured function. It will return true. You can see in the ButtonBase.cs file, at System.Windows.Forms.ButtonBase.OnFrameChanged, there is a line of code at the very end that says:
if (IsWindowObscured) {
StopAnimate();
return;
}
and therein lies the problem.
FYI, OnFrameChanged is called from the ImageAnimator thread. This is the callback that is specified in ImageAnimator.Animate(image, eventhandler). ButtonBase sets this up in the private void Animate(bool animate) function. The ImageAnimator thread polls every 50ms and checks to see if a new frame is necessary for any of the images it is monitoring; if so, it sets a flag to have the control invalidated and the new frame drawn.
Since this is inaccessible to us, I don't think there is much we can do about it. As a workaround, I implemented a timer in my form that invalidates the control every 500ms, so it will force it to restart if it had previously stopped. It is quite annoying that we can't override or even access it. I'm afraid the only solution is the hack above, or to create or use a control created by yourself or a third-party.
To clarify -- this is only a problem on Windows Vista or Windows 7 using desktop composition. The issue is that windows are never truly obscured, like they are when not using desktop composition. They are always buffered by the window manager. (There are special layered windows in windows 2000+, but ignore that for now). Previously, the parts of a window were not available if they were not on the screen or obscured by another window. When they came back into view, by changing focus or position etc, then the system will notify that area to repaint itself. However when using desktop composition, the repainting is never required, since the actual contents of the window are buffered elsewhere. This is why the window previews work in the taskbar, and Flip-3d, for example. The side effect is that code that expects to get a paint message when it is visible once again after being obscured will fail. The ButtonBase code expects to recieve a paint message once it comes back into view, which will start the animation again. And therefore, this optimization became a bug.
The issue should be reported in Microsoft Connect, though it is unlikely to be resolved.

Categories