Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: VS2008 C# Win7 WinForm
Hi all;
 
I'm writing a C# WinForms application for Win7 and higher in Visual Studio 2008. I'm on a 64 bit computer - ideally compiling for 32 bit, but the problem occurs either way.
I'm using the latest version of the Windows API Code Pack from here which has a lot of handy Win7-based features.
 
The thing I'm having difficulty with is the dialog CommonOpenFileDialog
I'm using it as a folder picker, but I have the issue in either mode.
It's fast to open, great for navigating my hard drive. However when I hit "Select Folder" to finalize my selection, my application hangs for (usually) five seconds. Windows even throws a "Not Responding" tag on the application name for a bit.
 
I can't find any instances of this happening to anyone else on Google, which is doubly bizarre.
I tried getting the latest version of the API Code Pack (I did not have it earlier), no change.
I tried restarting my computer, no change.
 
I swear I've had this dialog working for me before but it was a while ago..
I have a hard time believing it's the control itself causing the problem, I'm sure it works as advertised. Simultaneously I have a hard time believing my sample program (below) is using it incorrectly.
I tried debugging the API Code Pack source, and nowhere in the managed code did I find the delay - it's somewhere in the native code.
The native code calls FileOk in the code pack which calls FileOk in the sample program, which starts the timer.
When ShowDialog returns, the timer is stopped. There is a large delay here.
 
I timed the guts of ShowDialog after the call to the native ShowDialog, and that's all <1ms. So it's inside the native ShowDialog, after it calls FileOk and before it returns.
 
Can someone give me suggestions as to how to debug this problem? (No idea about unmanaged debugging) What else about my installation/computer/code could be causing trouble?
 
I recently upgraded to VS2008 SP1, and there are no more Windows Updates available for my PC. I'm at my wits end!
 
Thanks for your time;
William
 

I made a tiny sample form that repros the problem.
0. Create a new WinForms project
1. Download the file from the link above and extract.
2. Stick Microsoft.WindowsAPICodePack.Shell.dll and Microsoft.WindowsAPICodePack.dll from Binaries into the project directory and add references to them. [Alternatively do the same with the source, but it makes no difference]
3. Stick one button and one label on the form.
4. Output is in milliseconds.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.WindowsAPICodePack;
using Microsoft.WindowsAPICodePack.Dialogs;
using System.Diagnostics;
 
namespace CommonOpenFileDialog_Issues
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            label1.Text = "Click Browse... to begin";
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            label1.Text = "Waiting...";
            CommonOpenFileDialog cofd = new CommonOpenFileDialog("Why so slow to return?");
            cofd.IsFolderPicker = true;
            cofd.Multiselect = false;
            cofd.InitialDirectory = @"C:\";
            cofd.FileOk += new CancelEventHandler(cofd_FileOk);
 
            cofd.ShowDialog();
            sw.Stop();
            label1.Text = sw.ElapsedMilliseconds.ToString();
        }
 
        Stopwatch sw = new Stopwatch();
        /// <summary>
        /// Apparently called immediately before cofd.ShowDialog(); returns.
        /// However there is a HUGE delay between this event, and the function returning.
        /// It does not always happen (sometimes ~30ms as I might expect) but when it does, it takes 5 to 10 seconds.
        /// It occurs *at least* once every 20 tries.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void cofd_FileOk(object sender, CancelEventArgs e)
        {
            sw.Reset();
            sw.Start();
        }
    }
}
Posted 9-Feb-12 12:25pm
Edited 9-Feb-12 12:45pm
859.9K
v3
Comments
SAKryukov at 9-Feb-12 18:54pm
   
Thank you for accurately formulated question. This is so rare! I only had to add a tag WinForms to make if finally correct (it's important that expert could see right tags before loading this page). So, I voted 4 for the question; and I do it very rarely.
 
As to the question, I thing using this code pack itself is questionable. It makes the code much less portable. (Did you know that "normal" Forms application runs an many platforms under Mono without recompilation?), and as to the benefits...
 
The code is too simple to be wrong; I would assume you can blame Microsoft, not your self. Just a couple of notes on your code (unrelated to the problem): the names like "Form1", and those with underscore violate (good) Microsoft naming conventions. Auto-generated code is always invalid in this respect; you should always rename all auto-generated names to some semantic names; also, "cofd_FileOk" is redundant, I recommend using anonymous methods for handlers, as well as lambda syntax (for C# v>2).
 
--SA
TRK3 at 9-Feb-12 20:10pm
   
Good question. Very weird.
 
My first instinct is maybe there some horrible garbage collection going on. Try referencing something in cofd after you call sw.Stop() -- just to make sure it doesn't get GC'd until later.
 
I work mostly with unmanaged C++ and I have found that the CFileDialog does a lot of work.
 
For one thing, on my system (Win7 Pro), it throws an exception every time you open it "First-chance exception at 0x75bab9bc (KernelBase.dll) in MyApp.exe: 0x000006BA: The RPC server is unavailable." (It gets caught somewhere before it gets to my code, but it's a little jarring when your debugger breaks on an exception deep in the bowels of MS code every time you open a file dialog.)
 
Maybe on your system the "RPC Server" is actually available, so instead of throwing an exception and skipping all the remote stuff it actually does something remote over the network when it's opening the dialog. In which case it might also do something remote over the network when closing it (at which point all bets are off if your network is slow or the remote server is overloaded or down). That 5 second lag sounds supiciously like the sort of lag I see sometimes trying to access a DCOM application on another computer over the network -- of course in that case I know that the lag is related to the remote procedure call.
electrowizard at 10-Feb-12 13:17pm
   
@SAKryukov Thanks for your input, I'm glad you enjoyed my question format. Over at StackOverflow someone might have bitten my head off anyways; it's a much nicer environment here. Thanks for being nice :) (You too TRK3)
I have some questions about what you said, please give me your wisdom:
 
SAKryukov said:
"the names like "Form1", and those with underscore violate (good) Microsoft naming conventions. Auto-generated code is always invalid in this respect; you should always rename all auto-generated names to some semantic names; also, "cofd_FileOk" is redundant, I recommend using anonymous methods for handlers, as well as lambda syntax (for C# v>2)."
 
This started out well, but you lost me pretty quickly. For the purposes of the sample code I intentionally left the names as default so someone could copypasta the code into a new form easily. In production code I rename every Control I access from code (i.e. permanent text labels retain 'label1' etc.)
 
Can you explain why auto-generated could would violate naming conventions? - and consequently why this is a problem? I have always assumed the code it generates was a template that all my code should look like! Quite the opposite of what you indicate. Do you know of any good reading material on the subject you could recommend?
 
What makes "cofd_FileOk" redundant? The cofd has several events; this one is the FileOk event. I'm not sure how much more concise the event handler name could be..
I've never seen anonymous event handlers, so I looked them up. They look like this, right? item.OnKeyChanged += (o, k) => ChangeItemKey((T)o, k);
What is the benefit? It seems like much more typing, especially when writing many event handlers.
 
My application has no worries about portability, etc. In fact the only computers it will be installed on are ones we purchase specifically for running this program, installed in house, then shipped to the customer. This way we also guarantee Win7+ so the API Code Pack should be quite helpful, with no apparent drawbacks for us. Unless you have an alternative for handy Win7 integration I don't know about..?
 

@TRK3
Networking stuff sounds totally possible. I'm on a wireless network which has a file server attached.. I'll do some debugging with my networking disabled. I assume there's no way to disable attempting RPC or you would be doing it yourself :)
Yeah it's annoying when people use exceptions as flow control. I assume they had no choice for some reason - I guess I want to give them the benefit of the doubt.
I will also try avoiding the GC and see what happens.
Thanks for the suggestions
 

 
@all
1. Can anyone suggest a replacement Folder Picker? Other than the WinForms FolderBrowser of course - that thing is like garbage.
2. I'm using the "Have a Question or Comment" box below the comments and this thing is super tiny, like 6 lines tall. Is this common? I wish it had a preview like there was when I was submitting the question. Is there an alternative?
BillWoodruff at 10-Feb-12 19:38pm
   
TRK3 wrote: in response to SAK: "Can you explain why auto-generated could would violate naming conventions?"
 
I can tell you right now that he will never be able to explain his tendency to "sermonize" on this topic ad nauseam: because it's a part of an obsessive-compulsive personality trait. He also happens to be an incredible mind, a prodigy, and a source of great help to many people here on CP QA. I wonder: when he sleeps, if he dreams in code ? :)
 
Of course, on one level, he's absolutely right: a systematic naming scheme enforcing case-conventions for objects, methods, properties, fields, classes, etc., which (by case convention) helps express the "context of their scope" (locality vs. extra-locality, parameter vs. internal variable) is a very good thing: but you must realize that SAK is on a "crusade" here based on some inner conviction that he is the "light and the way." And, Prophets do need to howl.
 
I am surprised he has not shown up in Redmond, Washington, and covered the telephone poles near Microsoft's Headquarters with posters condemning Visual Studio's default naming conventions :) Or, at least called up Anders and ventilated his spleen.
 
But, we all have our "hot buttons:" I hate Arrays ! I share with SAK hating the old MDI architecture (now passe, praise be). I am a sworn member of the "Society for the Propagation of the Faith in Generic Lists and Dictionaries and the Suppression of Heretical Arrays" :)
electrowizard at 10-Feb-12 22:44pm
   
@Bill
Genuine laughter was produced.. I love how detailed you got, both on the technical side and your humour.
Thanks for that :)
Question for you now - do you eliminate arrays in every circumstance? I ask because I use Lists as often as possible (right now I'm coding a SortedDictionary of SortedDictionaries of Lists of Points so I'm with you) but what do you do when you have to load into memory over 100 images, over 1000x1000 pixels - and access them all quickly in every dimension? i.e. I access them both as 2d images, as well as linear arrays of one pixel across images.
What structure would you choose in this circumstance? Security is not a concern, only speed. [Let's just say it takes several minutes with my 8 core processor running at >3GHz, and my users won't nearly have as much.
 
If they load too many images my program runs out of memory :(
Were I a better programmer I would write something that could swap memory pages but in a managed language I'm not even sure how to approach that. Anyways I'm way off topic and don't expect answers to everything here.
 
Thanks again;
Will
BillWoodruff at 11-Feb-12 4:40am
   
@ElectroWizard: There was a very good answer or comment from, SAK, recently, here on QA, suggesting the use of a List<List<SomeType>> structure instead of an array:
 
http://www.codeproject.com/Answers/325337/I-want-to-use-generic-list-in-my-project-instead-o
 
SAK made several interesting observations how this structure gave you the benefits of a "jagged array."
 
It would be an interesting article indeed for CP, to see someone with major league skills, like SAK, or Luc Patyn, or Pete O'Hanlon, or Harold Aptroot, Bob Janova, Richard MacCutcheon, etc. take on a comparison of memory consumption and access time for Arrays in general vs. their Generic equivalents.
 
I would hypothesize that a known fixed size Array of a definite type, every entry of which is populated may be highly optimized by the compiler. On the other other hand, if I take your words very literally re "every dimension," and assume an array of [100,1000,1000]: filling it with 100 million pixel data entries (24/32 bytes each ?): I think I'd be waiting a long, long time, to fill the array on my current machine, where I'm not sure, with only 4gigs, I'd have room to spare for it anyhow :)
electrowizard at 12-Feb-12 15:15pm
   
@Bill
Thanks for the link; yes jagged arrays are quite useful in certain applications.
In mine the number of images is known just before array creation, and the image dimensions are always identical - so I need a perfect rectangular prism of pixel values.
 
Fortunately for me, the pixels are only Shorts (truly 10 bit but I'm not sure I want to make my own packed datatype), so the almost 200M pixel entries are only a few hundred MB of memory - filling it from image files takes only half a minute.
It's a tad slower, but I've also run it on a 2GHz dual core AMD with only 2GB ram.
 

My layman's impression is the space overhead from the lists would be seriously detrimental to the performance (and to actually having enough RAM!), so I would also be really interested in seeing a superstar do an Array/Generic space and speed comparison, for small and HUGE datasets, in increasing number of dimensions - i.e. 1D, 2D, 3D, 4D.. probably as far as you need to go in most cases I would imagine.. I don't think I've ever had more than a 3 or maybe 4 dimension array.
 
Thanks for a great conversation! I program alone at work - I miss the teamwork, camaraderie and learning from better programmers than myself.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 Nirav Prabtani 298
1 OriginalGriff 289
2 Sergey Alexandrovich Kryukov 225
3 _Amy 165
4 Richard MacCutchan 135
0 OriginalGriff 7,799
1 Sergey Alexandrovich Kryukov 6,966
2 Maciej Los 3,994
3 Peter Leow 3,708
4 CHill60 2,742


Advertise | Privacy | Mobile
Web02 | 2.8.140721.1 | Last Updated 10 Dec 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100