Click here to Skip to main content
15,867,330 members
Please Sign up or sign in to vote.
4.89/5 (2 votes)
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.
XML
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
Updated 9-Feb-12 12:45pm
v3
Comments
Sergey Alexandrovich Kryukov 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 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 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 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 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

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



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900