none
C# Browse for Folder dialog hangs if shown with Owner

    Question

  • I'm using the folder browser component from a library assembly (a plugin for another app).  This library assembly is being called from an application which is not single apartment threaded nor can I make it be one.  Unfortunately, it seems that this component requires STA as it throws an exception if called from any other threading model.  This is easily reproduced, and well documented.

    So what I am doing is creating a new SingleApartmentThreaded thread and calling ShowDialog() from that.  This works.  But of course it shows the dialog modelessly.  Not cool.  Should be simple enough, if I pass in a IWin32Window reference, it will show it as a child of that window, right?  Heh...not so.

    However, if I get the NativeWindow of the top-level window of the process that I'm running in, which I have verified with Spy is the correct handle, when I call ShowDialog() using that parent window handle it hangs.  I have reproduced this using my own Form in a test.  Whenever I pass in an owning window, it hangs.

    I assume this is because it is cross-thread?  The dialog is being shown in one thread, but the parent window is in another thread?

    If so is there some other workaround so that I can get this to show modally?  I can't show it in the main thread, because that is not STA?!?

    Of course I could write my own dialog, but that seems like an incredible waste of time?

    Thanks in advance for any help with this...



    • Edited by ryan.rogers Thursday, September 26, 2013 5:08 PM
    Thursday, September 26, 2013 3:48 PM

Answers

  • Actually I figured it out once I stepped away from it a bit and started really thinking about what was going on.

    Since I had to create a separate STATHREAD in order for the component to work, I had to have my main thread wait until the dialog was done showing so that it could return to the calling application the selected folder.  So I had done a Thread.Join().  However that native calling thread I had just blocked was already running the message pump for the Win32 process.  Since the caller wasn't my code, I couldn't be sure.

    So after starting the thread I had to replace the Join() call with a loop that runs while the dialog is being shown (in the other thread) and repeatedly calls Application.DoEvents().

    Then everything worked like a charm!

     

    Saturday, September 28, 2013 5:13 PM

All replies

  • Hi Ryan,

    I think this thread is not relate to IWin32Window and STA. Per my understanding, the root cause is Application.BeginModalMessageLoop method. This method blocks the application return to the previous window. Application.EndModalMessageLoop method ends it. MessageBox.Show and OpenFileDialog.ShowDialog are do the same thing.

    To troubleshoot this issue, we really need the source code to reproduce the problem. Please send out the whole code to me using SkyDrive. You could remove any confidential information or business logic from it.

    I’m look forward to hearing from you.

    Best Regards,


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    Friday, September 27, 2013 10:00 AM
  • Actually I figured it out once I stepped away from it a bit and started really thinking about what was going on.

    Since I had to create a separate STATHREAD in order for the component to work, I had to have my main thread wait until the dialog was done showing so that it could return to the calling application the selected folder.  So I had done a Thread.Join().  However that native calling thread I had just blocked was already running the message pump for the Win32 process.  Since the caller wasn't my code, I couldn't be sure.

    So after starting the thread I had to replace the Join() call with a loop that runs while the dialog is being shown (in the other thread) and repeatedly calls Application.DoEvents().

    Then everything worked like a charm!

     

    Saturday, September 28, 2013 5:13 PM