I've got a complex WPF application with windows on multiple threads. Quite reproducibly, it happens that when I open and close a new window, the focus (activation) does not go back to the last activated window. Instead an (usually) older window gets activated. Since the workflow is "working in window A", "opening windows B, C from A", "working with B, C", "open window D from B", "close D", I'd need windows to return focus to B, but actually it goes to A.
I've already taken a look at stacktraces around the Window.Activated and Window.Deactivated events, but those come directly from the WPF infrastructure and do not show any clues. I've already tried Spy++, but its usefulness is ... limited.
How can I debug this further?
Update: The phenomenon vanished after I stopped blocking the thread of B for longer periods of time when creating D. It seems to be the case that the desktop window manager becomes confused, when threads block their message pump. I've plastered over the problem by pushing the message-pump blockers onto the Dispatcher with background priority before creating D. This seems to clear up any DWM confusion and windows activation doesn't act up anymore. I'd still be interested in pointers to a more in-depth solution/analysis.
You might not want to hear this but in these situations the next step I take is to examine the reference source for the the methods immediately in the stack of the relevant phenomenon. I don't know if you've use reference source before:
Microsoft Reference Source
Get this set up and then set up a breakpoint at the usual spot, say a focus event. Now look up the stack. You should be able to double-click and see source code for most of the stack frames. Of course it's a crap shoot but in any case better than looking at method names.
If you find you want to inspect some variables on the reference source side you'll find they don't work. Use this fix:
How to disable optimizations when debugging Reference Source
I know this is not very specific but this is what I would try next.
Related
I'm looking at improving developer experience when running graphics tests which spawn short-lived windows "like crazy". The windows need to be physically there, as otherwise data readback fails (i.e. the window cannot be hidden)
Needless to say, windows popping up at high frequency is unpleasant. I set out with the goal of finding a way to tell XCreateWindow to "create the window in the background", "not to steal focus" or something like that to no avail. The closest thing I could find is calling XSetInputFocus post-creation. Other than the fact that I couldn't make it work, I don't expect setting input focus to fully solve the issue anyway (as the windows would still pop up, just not without input focus, right?).
How is this done in X11?
P.S. The update notification on Ubuntu starts without popping to front, so this must be a possibility.
In the past I've tried and admitedly failed doing what you want to do. Nevertheless I've found a few "close-enough"-solutions that may be of interest.
XCreatePixmap might work out, but in my case didn't have a pixmap with desired properties (multisampling) so it "out the window" (haha)
To prevent some level of spaming you might be able to set XCreateWindow parent to a an exisiting window other than root, large enough to hold your tests and moved outside display. The parent window need be created, moved outside display and un-focused, but at least every window creation won't steal focus (I think) and spam on display.
Or you figure out a way to create additional displays, maybe using Xvbf. Didn't have admin access to corp dev env so didn't bother trying to install/configure, in addition to other obstacles, but it might just work for you.
I try to send for the Open event of the window from the event ItemChanged a DataWindow using the: SUPER :: EVENT OPEN () in addition to the open event contains "script ancestor" I also need to run; itself need to restart the window from the event ItemChanged of a DataWindow.
I hope your help.
Thanks in advance.
Regards,
A few things jump out from your question.
SUPER::EVENT OPEN() will try to call the Open event of the DataWindow if called from the ItemChanged, not the Window.
I'm not 100% sure of this, but I'm pretty sure I've run into problems trying to call the ancestor of one script from a completely different script. I can't point to documentation; I'll have to just chalk it up to experienced suspicion.
It's not entirely clear what you're after, but if you want to call the Open of the window (and I'll suggest otherwise below), and if the window's Open script either extends the ancestor script or explicitly calls the ancestor script (as above), explicitly calling the ancestor script is unnecessary, and strikes me as potentially undesirable. Just call the Open script of the window you're writing.
This will depend entirely on your code, but of the dozens of systems I've had to maintain, I'd never assume that running the Open event of a Window would "restart" the window. Most systems I've worked on, that would just create an unexpected mix of previous and new states. Additionally, even if I coded this from scratch to work perfectly in this way, I'd assume that the next guy that came along to maintain my code (after I won the lottery and retired to a small South Pacific island) would code in a way that made perfect sense to him based on other systems he worked on, but would screw up my assumptions. If I needed to "restart" the window, I would either:
close the window and post an Open() (the function, not the event) of the window again
create a ue_ResetWindow event, hopefully coding so that the Open could use it as well, that made it obvious that anything added to the window needed to be maintained in this script as well
(Of the two, the latter would be far better user experience and coding, IMHO.)
Good luck,
Terry.
I am trying to pro-actively ensure I am not causing memory leaks in my code by keeping an extra weak reference to an object, and checking it is no longer active when it should be released (this is conditional code so it only runs when I am testing).
To simply reproduce the effect I am seeing, create a new WPF Application and put a Button on the main window. Create another window, and put a TextBox on it. In the click handler for the button, put the following code:
Window1 w = new Window1();
WeakReference weak = new WeakReference(w);
w.ShowDialog();
w = null;
// Equivalent to Application.DoEvents() just in case...
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate { }));
GC.Collect();
GC.WaitForPendingFinalizers();
if (weak.Target != null)
MessageBox.Show("Memory Leak");
When you run this, click on the button and when the window displays, just click on the 'x' to close it and nothing happens - all good. Now do the same thing, but when the window displays, click into the TextBox and then click on 'x'. I get the "Memory Leak" message every time.
Ants Profiler shows System.Windows.Documents.TextEditor has a reference to the TextBox (which presumably gets set up only if you focus the TextBox), and the TextBox has a reference to the window. Its not a real memory leak because if you do the process multiple times, previous windows get collected, just not the latest. However, it means I cannot write tests that confirm memory is not leaking.
Am I the only person wanting this level of assurance, or is there another way?
I think some people have missed the point of your question. You're not trying to force GC's hand, but rather preemptively discover any memory leaks, and for that I applaud you.
In this particular case, it appears as though TextEditor (which is internal) is adding event handlers and has not yet had a chance to detach when your check runs. Have you tried explicitly shifting focus out of the closed window before pumping the dispatcher?
I think you will continue to run into these kind of issues if you attempt to do these tests in your application proper, rather than in the more controlled environment of integration tests, so perhaps you need to re-think your approach.
If previous instances get collected, it's not a memory leak. The garbage collector doesn't always take the most recent items, and it's by design. If you try to second-guess it you'll likely run into problems.
In a real memory leak items will accumulate without ever being reclaimed. That's something best detected using the profiler.
Windows are not just managed by your code but also by some WPF classes like Application. Calling Collect does not guarantee or prove anything, the window does get collected eventually.
try with DispatcherPriority.ContextIdle
Dispatcher.CurrentDispatcher.Invoke( DispatcherPriority.ContextIdle, new System.Action(delegate { }));
We've created a new, quite complex, WPF application from the ground up and have run into a performance problem as the number of commands registered with the CommandManager increase. We're using simple lightweight commands in our MVVM implementation, however the third party controls we're using (Infragistics) do not, and call CommandManager.RegisterClassCommandBinding liberally to add RoutedCommands. The performance problem manifests itself as a perceived sluggishness in the UI when responding to user input, for example tabbing between controls is slow, text input is 'jerky' and popup animation is 'clunky'. When the app is first fired up the UI is snappy. As more screens containing Infragistics grids are opened the performance deteriorates.
Internally, the CommandManager has a private field named _requerySuggestedHandlers, which is a List< WeakReference>. I've used reflection to get a reference to this collection, and I've noticed that when I call .Clear(), the responsiveness of the UI improves back to its initial state. Obviously I don't want to go round clearing collections that I know little about, especially using reflection (!) but I did it to see if it would cure the performance problems, and voila it did.
Normally, this situation would clean itself up after a certain amount of time passes. However, the collection of WeakReferences (_requerySuggestedHandlers) will only get trimmed once a garbage collection is initiated, which is non-deterministic. Because of this, when we close down windows containing grids (Infragistics XamDataGrid), the CanExecute property for 'dead' grid commands continue to be evaluated unnecessarily, long after the window is closed. This also means that if we close down a number of windows, the performance is still sluggish until a garbage collect is initiated. I understand that this can happen on allocation, and I've seen that myself because if I open a further window this causes the initial memory (from the disposed Windows) to be collected and performance returns to normal.
So, given the above, here are my questions:
How, and from where, does CommandManager.InvalidateRequerySuggested() get called? I haven't found any documentation on MSDN that explains this in any great detail. I hooked up to the CommandManager.RequerySuggested event and it looks like it's being called whenever controls lose focus.
Is is possible to suppress CommandManager.InvalidateRequerySuggested() being called in response to user input?
Has anyone else run into this issue, and if so, how have you avoided it?
Thanks!
This sounds like one of the rare cases where deterministically calling GC.Collect() is the right thing to do. The ordinary argument against it is that the garbage collector is smarter than you are. But when you're dealing with WeakReference objects, you enter territory where you may know something that the garbage collector doesn't. Kicking off garbage collection is certainly better than clearing _requerySuggestedHandlers - among other things, it won't do anything to the WeakReference objects that point to controls that are still alive.
I'd choose this over trying to figure out how to suppress RequerySuggested, since that would screw up the behavior of those commands that you still care about.
I've hit against what I think is a race condition. What options do I have to debug it?
More details:
I have a Silverlight application which uses Telerik grid. The columns can be customised by the user by using a column chooser attached to the grid. In a particular case where the list of possible columns are created via the code, when I open the column chooser and close it, the data in the grid (all the rows) disappear!
Symptoms that I see which lead me to believe it is a race condition:
- If I put a break point at the columnchooser.close line, and when the break point is hit, just continue, the bug is not visible (all the gird rows remain visible)
- If I put a Thread.Sleep(1000) in the code just before columnchooser.close, again the bug disappears
- If I keep the "Threads" window in Visual Studio open while debugging, I see a thread momentarily appear and disappear in the Threads window just as I hit the breakpoint at columnchooser.close
So, I tried the following to figure out which threads are running at that point in time - but no joy:
System.Diagnostics.Process is not available in Silverlight, so I can't do System.Diagnostics.Process.Threads to get a list of the threads running programmatically.
I tried a break point with a "When hit" run Macros.Samples.VSDebugger.DumpStacks, but I couldn't figure out where it was dumping all the stack traces to.
Any help or ideas on what I can do to debug this issue?
Without the code this is necessarily vague, but have you looked into putting a lock on the columns or even the grid itself.
I'm not sure how this would actually work, but if (as you imply) the problem is due to the column chooser and the column creation code trying to access the grid at the same time then this might solve it.